From 8d621f247fe7c2a5a8c1da4adc720cbb996c1afb Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Fri, 6 Feb 2015 09:20:16 +0100
Subject: [PATCH 01/25] Remove admin extension from this repo.
---
.../core/commands/templates/settings.py.tpl | 1 -
modoboa/core/views/auth.py | 3 +-
modoboa/extensions/admin/__init__.py | 0
modoboa/extensions/admin/app_settings.py | 100 ----
modoboa/extensions/admin/factories.py | 79 ---
modoboa/extensions/admin/fixtures/demo.json | 310 ----------
modoboa/extensions/admin/forms/__init__.py | 19 -
modoboa/extensions/admin/forms/account.py | 478 ---------------
modoboa/extensions/admin/forms/alias.py | 152 -----
modoboa/extensions/admin/forms/domain.py | 362 ------------
modoboa/extensions/admin/forms/export.py | 45 --
modoboa/extensions/admin/forms/forward.py | 46 --
modoboa/extensions/admin/forms/import_.py | 43 --
modoboa/extensions/admin/lib.py | 114 ----
.../extensions/admin/management/__init__.py | 0
.../admin/management/commands/__init__.py | 0
.../commands/handle_mailbox_operations.py | 97 ---
.../admin/migrations/0001_initial.py | 161 -----
.../extensions/admin/migrations/__init__.py | 0
modoboa/extensions/admin/models/__init__.py | 10 -
modoboa/extensions/admin/models/alias.py | 210 -------
modoboa/extensions/admin/models/base.py | 81 ---
modoboa/extensions/admin/models/domain.py | 185 ------
.../extensions/admin/models/domain_alias.py | 72 ---
modoboa/extensions/admin/models/mailbox.py | 334 -----------
modoboa/extensions/admin/modo_extension.py | 285 ---------
.../admin/static/admin/css/admin.css | 33 --
.../admin/static/admin/css/settings.css | 9 -
.../extensions/admin/static/admin/js/admin.js | 556 ------------------
modoboa/extensions/admin/tables.py | 15 -
.../templates/admin/account_general_form.html | 12 -
.../admin/templates/admin/aliasform.html | 10 -
.../templates/admin/domain_general_form.html | 5 -
.../templates/admin/domain_options_form.html | 8 -
.../templates/admin/domain_statistics.html | 63 --
.../admin/templates/admin/domains.html | 29 -
.../admin/templates/admin/domains_table.html | 9 -
.../admin/templates/admin/editdomainform.html | 28 -
.../admin/templates/admin/forward.html | 11 -
.../admin/templates/admin/header.html | 12 -
.../admin/templates/admin/identities.html | 26 -
.../templates/admin/identities_table.html | 10 -
.../templates/admin/identity_headers.html | 5 -
.../admin/templates/admin/import_done.html | 11 -
.../admin/templates/admin/importform.html | 16 -
.../admin/templates/admin/listing.html | 47 --
.../admin/templates/admin/mailboxes_raw.html | 11 -
.../admin/templates/admin/mailform.html | 5 -
.../admin/templates/admin/newdomainform.html | 6 -
.../admin/templates/admin/permsform.html | 2 -
.../admin/templates/admin/quota_headers.html | 5 -
.../admin/templates/admin/quotas.html | 15 -
.../admin/templates/admin/searchform.html | 11 -
.../extensions/admin/templatetags/__init__.py | 0
.../admin/templatetags/admin_tags.py | 280 ---------
modoboa/extensions/admin/tests/__init__.py | 14 -
modoboa/extensions/admin/tests/account.py | 197 -------
modoboa/extensions/admin/tests/alias.py | 130 ----
modoboa/extensions/admin/tests/domain.py | 112 ----
.../extensions/admin/tests/domain_alias.py | 47 --
modoboa/extensions/admin/tests/export.py | 84 ---
modoboa/extensions/admin/tests/import_.py | 191 ------
.../admin/tests/password_schemes.py | 55 --
modoboa/extensions/admin/tests/user.py | 26 -
modoboa/extensions/admin/urls.py | 60 --
modoboa/extensions/admin/views/__init__.py | 0
modoboa/extensions/admin/views/alias.py | 135 -----
modoboa/extensions/admin/views/domain.py | 154 -----
modoboa/extensions/admin/views/export.py | 90 ---
modoboa/extensions/admin/views/identity.py | 211 -------
modoboa/extensions/admin/views/import.py | 177 ------
modoboa/extensions/admin/views/user.py | 57 --
modoboa/lib/web_utils.py | 3 +-
73 files changed, 4 insertions(+), 6176 deletions(-)
delete mode 100644 modoboa/extensions/admin/__init__.py
delete mode 100644 modoboa/extensions/admin/app_settings.py
delete mode 100644 modoboa/extensions/admin/factories.py
delete mode 100644 modoboa/extensions/admin/fixtures/demo.json
delete mode 100644 modoboa/extensions/admin/forms/__init__.py
delete mode 100644 modoboa/extensions/admin/forms/account.py
delete mode 100644 modoboa/extensions/admin/forms/alias.py
delete mode 100644 modoboa/extensions/admin/forms/domain.py
delete mode 100644 modoboa/extensions/admin/forms/export.py
delete mode 100644 modoboa/extensions/admin/forms/forward.py
delete mode 100644 modoboa/extensions/admin/forms/import_.py
delete mode 100644 modoboa/extensions/admin/lib.py
delete mode 100644 modoboa/extensions/admin/management/__init__.py
delete mode 100644 modoboa/extensions/admin/management/commands/__init__.py
delete mode 100644 modoboa/extensions/admin/management/commands/handle_mailbox_operations.py
delete mode 100644 modoboa/extensions/admin/migrations/0001_initial.py
delete mode 100644 modoboa/extensions/admin/migrations/__init__.py
delete mode 100644 modoboa/extensions/admin/models/__init__.py
delete mode 100644 modoboa/extensions/admin/models/alias.py
delete mode 100644 modoboa/extensions/admin/models/base.py
delete mode 100644 modoboa/extensions/admin/models/domain.py
delete mode 100644 modoboa/extensions/admin/models/domain_alias.py
delete mode 100644 modoboa/extensions/admin/models/mailbox.py
delete mode 100644 modoboa/extensions/admin/modo_extension.py
delete mode 100644 modoboa/extensions/admin/static/admin/css/admin.css
delete mode 100644 modoboa/extensions/admin/static/admin/css/settings.css
delete mode 100644 modoboa/extensions/admin/static/admin/js/admin.js
delete mode 100644 modoboa/extensions/admin/tables.py
delete mode 100644 modoboa/extensions/admin/templates/admin/account_general_form.html
delete mode 100644 modoboa/extensions/admin/templates/admin/aliasform.html
delete mode 100644 modoboa/extensions/admin/templates/admin/domain_general_form.html
delete mode 100644 modoboa/extensions/admin/templates/admin/domain_options_form.html
delete mode 100644 modoboa/extensions/admin/templates/admin/domain_statistics.html
delete mode 100644 modoboa/extensions/admin/templates/admin/domains.html
delete mode 100644 modoboa/extensions/admin/templates/admin/domains_table.html
delete mode 100644 modoboa/extensions/admin/templates/admin/editdomainform.html
delete mode 100644 modoboa/extensions/admin/templates/admin/forward.html
delete mode 100644 modoboa/extensions/admin/templates/admin/header.html
delete mode 100644 modoboa/extensions/admin/templates/admin/identities.html
delete mode 100644 modoboa/extensions/admin/templates/admin/identities_table.html
delete mode 100644 modoboa/extensions/admin/templates/admin/identity_headers.html
delete mode 100644 modoboa/extensions/admin/templates/admin/import_done.html
delete mode 100644 modoboa/extensions/admin/templates/admin/importform.html
delete mode 100644 modoboa/extensions/admin/templates/admin/listing.html
delete mode 100644 modoboa/extensions/admin/templates/admin/mailboxes_raw.html
delete mode 100644 modoboa/extensions/admin/templates/admin/mailform.html
delete mode 100644 modoboa/extensions/admin/templates/admin/newdomainform.html
delete mode 100644 modoboa/extensions/admin/templates/admin/permsform.html
delete mode 100644 modoboa/extensions/admin/templates/admin/quota_headers.html
delete mode 100644 modoboa/extensions/admin/templates/admin/quotas.html
delete mode 100644 modoboa/extensions/admin/templates/admin/searchform.html
delete mode 100644 modoboa/extensions/admin/templatetags/__init__.py
delete mode 100644 modoboa/extensions/admin/templatetags/admin_tags.py
delete mode 100644 modoboa/extensions/admin/tests/__init__.py
delete mode 100644 modoboa/extensions/admin/tests/account.py
delete mode 100644 modoboa/extensions/admin/tests/alias.py
delete mode 100644 modoboa/extensions/admin/tests/domain.py
delete mode 100644 modoboa/extensions/admin/tests/domain_alias.py
delete mode 100644 modoboa/extensions/admin/tests/export.py
delete mode 100644 modoboa/extensions/admin/tests/import_.py
delete mode 100644 modoboa/extensions/admin/tests/password_schemes.py
delete mode 100644 modoboa/extensions/admin/tests/user.py
delete mode 100644 modoboa/extensions/admin/urls.py
delete mode 100644 modoboa/extensions/admin/views/__init__.py
delete mode 100644 modoboa/extensions/admin/views/alias.py
delete mode 100644 modoboa/extensions/admin/views/domain.py
delete mode 100644 modoboa/extensions/admin/views/export.py
delete mode 100644 modoboa/extensions/admin/views/identity.py
delete mode 100644 modoboa/extensions/admin/views/import.py
delete mode 100644 modoboa/extensions/admin/views/user.py
diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl
index 2ba6dc86b..c19db186e 100644
--- a/modoboa/core/commands/templates/settings.py.tpl
+++ b/modoboa/core/commands/templates/settings.py.tpl
@@ -57,7 +57,6 @@ MODOBOA_APPS = (
'modoboa.core',
'modoboa.lib',
# Modoboa extensions here.
- 'modoboa.extensions.admin',
'modoboa.extensions.postfix_relay_domains',
'modoboa.extensions.limits',
'modoboa.extensions.postfix_autoreply',
diff --git a/modoboa/core/views/auth.py b/modoboa/core/views/auth.py
index 44325a366..e515cb61f 100644
--- a/modoboa/core/views/auth.py
+++ b/modoboa/core/views/auth.py
@@ -41,7 +41,8 @@ def dologin(request):
if user.group == "SimpleUsers":
nextlocation = reverse("topredirection")
else:
- nextlocation = reverse("admin:domain_list")
+ # FIXME
+ nextlocation = reverse("modoboa_admin:domain_list")
return HttpResponseRedirect(nextlocation)
error = _(
"Your username and password didn't match. Please try again.")
diff --git a/modoboa/extensions/admin/__init__.py b/modoboa/extensions/admin/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/admin/app_settings.py b/modoboa/extensions/admin/app_settings.py
deleted file mode 100644
index 8638bce9e..000000000
--- a/modoboa/extensions/admin/app_settings.py
+++ /dev/null
@@ -1,100 +0,0 @@
-from django import forms
-from django.conf import settings
-from django.utils.translation import ugettext_lazy
-from modoboa.lib.form_utils import YesNoField, SeparatorField
-from modoboa.lib.sysutils import exec_cmd
-from modoboa.lib import parameters
-import os
-
-
-class AdminParametersForm(parameters.AdminParametersForm):
- app = "admin"
-
- mbsep = SeparatorField(label=ugettext_lazy("Mailboxes"))
-
- handle_mailboxes = YesNoField(
- label=ugettext_lazy("Handle mailboxes on filesystem"),
- initial="no",
- help_text=ugettext_lazy(
- "Rename or remove mailboxes on the filesystem when they get"
- " renamed or removed within Modoboa"
- )
- )
-
- mailboxes_owner = forms.CharField(
- label=ugettext_lazy("Mailboxes owner"),
- initial="vmail",
- help_text=ugettext_lazy(
- "The UNIX account who owns mailboxes on the filesystem"
- )
- )
-
- default_domain_quota = forms.IntegerField(
- label=ugettext_lazy("Default domain quota"),
- initial=0,
- help_text=ugettext_lazy(
- "Default quota (in MB) applied to freshly created domains with no "
- "value specified. A value of 0 means no quota."
- )
- )
-
- auto_account_removal = YesNoField(
- label=ugettext_lazy("Automatic account removal"),
- initial="no",
- help_text=ugettext_lazy(
- "When a mailbox is removed, also remove the associated account")
- )
-
- auto_create_domain_and_mailbox = YesNoField(
- label=ugettext_lazy("Automatic domain/mailbox creation"),
- initial="yes",
- help_text=ugettext_lazy(
- "Create a domain and a mailbox when an account is automatically "
- "created."
- )
- )
-
- # Visibility rules
- visibility_rules = {
- "mailboxes_owner": "handle_mailboxes=yes",
- }
-
- def __init__(self, *args, **kwargs):
- super(AdminParametersForm, self).__init__(*args, **kwargs)
- self.field_widths = {
- "default_domain_quota": 2
- }
- hide_fields = False
- dpath = None
- code, output = exec_cmd("which dovecot")
- if not code:
- dpath = output.strip()
- else:
- known_paths = getattr(
- settings, "DOVECOT_LOOKUP_PATH",
- ("/usr/sbin/dovecot", "/usr/local/sbin/dovecot")
- )
- for fpath in known_paths:
- if os.path.isfile(fpath) and os.access(fpath, os.X_OK):
- dpath = fpath
- if dpath:
- try:
- code, version = exec_cmd("%s --version" % dpath)
- except OSError:
- hide_fields = True
- else:
- if code or not version.strip().startswith("2"):
- hide_fields = True
- else:
- hide_fields = True
- if hide_fields:
- del self.fields["handle_mailboxes"]
- del self.fields["mailboxes_owner"]
-
- def clean_default_domain_quota(self):
- """Ensure quota is a positive integer."""
- if self.cleaned_data['default_domain_quota'] < 0:
- raise forms.ValidationError(
- ugettext_lazy('Must be a positive integer')
- )
- return self.cleaned_data['default_domain_quota']
diff --git a/modoboa/extensions/admin/factories.py b/modoboa/extensions/admin/factories.py
deleted file mode 100644
index e49956e83..000000000
--- a/modoboa/extensions/admin/factories.py
+++ /dev/null
@@ -1,79 +0,0 @@
-"""
-Fixtures factories.
-"""
-import factory
-
-from modoboa.core.factories import PermissionFactory, UserFactory
-from . import models
-
-
-class DomainFactory(PermissionFactory):
-
- """Factory to create Domains."""
-
- class Meta:
- model = models.Domain
- django_get_or_create = ("name", )
-
- quota = 10
- enabled = True
-
-
-class MailboxFactory(PermissionFactory):
-
- class Meta:
- model = models.Mailbox
-
- domain = factory.SubFactory(DomainFactory)
- user = factory.SubFactory(UserFactory)
- quota = 10
- enabled = True
-
-
-class AliasFactory(PermissionFactory):
-
- class Meta:
- model = models.Alias
-
- enabled = True
-
-
-def populate_database():
- """Create test data.
-
- 2 domains, 1 domain admin, 2 users
- """
- dom = DomainFactory(name="test.com")
- admin = UserFactory(
- username="admin@test.com", groups=('DomainAdmins', ),
- password='{PLAIN}toto'
- )
- MailboxFactory(address='admin', domain=dom, user=admin)
- account = UserFactory.create(
- username="user@test.com", groups=('SimpleUsers',),
- )
- MailboxFactory.create(address='user', domain=dom, user=account)
-
- fwd = AliasFactory.create(
- address='forward', domain=dom, extmboxes='user@external.com'
- )
- al = AliasFactory.create(
- address='alias', domain=dom
- )
- al.mboxes.add(account.mailbox_set.all()[0])
- AliasFactory.create(
- address='postmaster', domain=dom, extmboxes='toto@titi.com,test@truc.fr'
- )
- dom.add_admin(admin)
-
- dom2 = DomainFactory.create(name='test2.com', quota=0)
- admin = UserFactory.create(
- username='admin@test2.com', groups=('DomainAdmins',),
- password='{PLAIN}toto'
- )
- MailboxFactory.create(address='admin', domain=dom2, user=admin)
- u = UserFactory.create(
- username='user@test2.com', groups=('SimpleUsers',)
- )
- MailboxFactory.create(address='user', domain=dom2, user=u)
- dom2.add_admin(admin)
diff --git a/modoboa/extensions/admin/fixtures/demo.json b/modoboa/extensions/admin/fixtures/demo.json
deleted file mode 100644
index d3691219b..000000000
--- a/modoboa/extensions/admin/fixtures/demo.json
+++ /dev/null
@@ -1,310 +0,0 @@
-[
- {
- "pk": 1,
- "model": "core.user",
- "fields": {
- "username": "admin",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": true,
- "is_staff": false,
- "last_login": "2012-05-03T16:58:51+01:00",
- "groups": [],
- "user_permissions": [],
- "password": "{CRYPT}dTTsGDkA5ZHKg",
- "email": "",
- "date_joined": "2012-01-26T15:19:25+01:00"
- }
- },
- {
- "pk": 2,
- "model": "core.user",
- "fields": {
- "username": "admin@demo.local",
- "first_name": "Demo",
- "last_name": "Administrator",
- "is_active": true,
- "is_superuser": false,
- "is_staff": false,
- "last_login": "2012-05-24T05:00:12+01:00",
- "groups": [1],
- "user_permissions": [],
- "password": "{CRYPT}SJ2bQWwabfH/6",
- "email": "admin@demo.local",
- "date_joined": "2012-05-03T16:50:15+01:00"
- }
- },
- {
- "pk": 4,
- "model": "core.user",
- "fields": {
- "username": "user@demo.local",
- "first_name": "Demo", "last_name": "User",
- "is_active": true,
- "is_superuser": false,
- "is_staff": false,
- "last_login": "2012-05-03T16:56:50+01:00",
- "groups": [2],
- "user_permissions": [],
- "password": "{CRYPT}2iAFXtxUA6.7Y",
- "email": "user@demo.local",
- "date_joined": "2012-05-03T16:56:50+01:00"
- }
- },
- {
- "pk": 2,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": true,
- "user": 1,
- "content_type": ["admin", "domain"],
- "object_id": 1
- }
- },
- {
- "pk": 3,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": true,
- "user": 1,
- "content_type": ["core", "user"],
- "object_id": 2
- }
- },
- {
- "pk": 4,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": true,
- "user": 1,
- "content_type": ["admin", "mailbox"],
- "object_id": 1
- }
- },
- {
- "pk": 5,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": true,
- "user": 1,
- "content_type": ["admin", "alias"],
- "object_id": 1
- }
- },
- {
- "pk": 6,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": false,
- "user": 2,
- "content_type": ["admin", "domain"],
- "object_id": 1
- }
- },
- {
- "pk": 7,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": false,
- "user": 2,
- "content_type": ["admin", "mailbox"],
- "object_id": 1
- }
- },
- {
- "pk": 8,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": false,
- "user": 2,
- "content_type": ["core", "user"],
- "object_id": 2
- }
- },
- {
- "pk": 9,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": false,
- "user": 2,
- "content_type": ["admin",
- "alias"],
- "object_id": 1}},
- {
- "pk": 13,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": true,
- "user": 1,
- "content_type": ["core",
- "user"],
- "object_id": 4}},
- {
- "pk": 14,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": true,
- "user": 1,
- "content_type": ["admin",
- "mailbox"],
- "object_id": 3}},
- {
- "pk": 15,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": false,
- "user": 2,
- "content_type": ["admin",
- "mailbox"],
- "object_id": 3}},
- {
- "pk": 16,
- "model": "core.objectaccess",
- "fields": {
- "is_owner": false,
- "user": 2,
- "content_type": ["core",
- "user"],
- "object_id": 4}},
- {
- "pk": 1,
- "model": "admin.objectdates",
- "fields": {
- "creation": "2012-05-03T16:49:40+01:00",
- "last_modification": "2012-05-03T16:49:40+01:00"}},
- {
- "pk": 2,
- "model": "admin.objectdates",
- "fields": {
- "creation": "2012-05-03T16:50:15+01:00",
- "last_modification": "2012-05-03T16:50:36+01:00"}},
- {
- "pk": 3,
- "model": "admin.objectdates",
- "fields": {
- "creation": "2012-05-03T16:50:15+01:00",
- "last_modification": "2012-05-03T16:50:15+01:00"}},
- {
- "pk": 4,
- "model": "admin.objectdates",
- "fields": {
- "creation": "2012-05-03T16:51:04+01:00",
- "last_modification": "2012-05-03T16:51:04+01:00"}},
- {
- "pk": 5,
- "model": "admin.objectdates",
- "fields": {
- "creation": "2012-05-03T16:56:50+01:00",
- "last_modification": "2012-05-03T16:56:50+01:00"}},
- {
- "pk": 1,
- "model": "admin.domain",
- "fields": {
- "dates": 1,
- "enabled": true,
- "name": "demo.local",
- "quota": 10}},
- {
- "pk": 1,
- "model": "admin.mailbox",
- "fields": {
- "dates": 2,
- "quota": 10,
- "user": 2,
- "domain": 1,
- "address": "admin"
- }
- },
- {
- "pk": 3,
- "model": "admin.mailbox",
- "fields": {
- "dates": 5,
- "quota": 10,
- "user": 4,
- "domain": 1,
- "address": "user"
- }
- },
- {
- "pk": 1,
- "model": "admin.alias",
- "fields": {
- "dates": 3,
- "enabled": true,
- "domain": 1,
- "mboxes": [1],
- "address": "postmaster",
- "extmboxes": ""}},
- {
- "pk": 1,
- "model": "core.extension",
- "fields": {
- "enabled": true,
- "name": "limits"}},
- {
- "pk": 2,
- "model": "core.extension",
- "fields": {
- "enabled": true,
- "name": "postfix_autoreply"}},
- {
- "pk": 3,
- "model": "core.extension",
- "fields": {
- "enabled": true,
- "name": "stats"}},
- {
- "pk": 4,
- "model": "core.extension",
- "fields": {
- "enabled": true,
- "name": "amavis"}},
- {
- "pk": 5,
- "model": "core.extension",
- "fields": {
- "enabled": true,
- "name": "webmail"}},
- {
- "pk": 6,
- "model": "core.extension",
- "fields": {
- "enabled": true,
- "name": "sievefilters"}},
- {
- "pk": 7,
- "model": "core.extension",
- "fields": {
- "enabled": true,
- "name": "postfix_relay_domains"
- }
- },
- {
- "pk": 8,
- "model": "core.extension",
- "fields": {
- "enabled": true,
- "name": "radicale"
- }
- },
- {
- "pk": "admin@demo.local",
- "model": "admin.quota",
- "fields": {
- "username": "admin@demo.local",
- "bytes": 0,
- "messages": 0
- }
- },
- {
- "pk": "user@demo.local",
- "model": "admin.quota",
- "fields": {
- "username": "user@demo.local",
- "bytes": 0,
- "messages": 0
- }
- }
-]
diff --git a/modoboa/extensions/admin/forms/__init__.py b/modoboa/extensions/admin/forms/__init__.py
deleted file mode 100644
index dbb5a36ef..000000000
--- a/modoboa/extensions/admin/forms/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from .domain import (
- DomainFormGeneral, DomainFormOptions, DomainForm, DomainWizard
-)
-from .account import (
- AccountFormGeneral, AccountFormMail, AccountPermissionsForm,
- AccountForm, AccountWizard
-)
-from .alias import AliasForm
-from .forward import ForwardForm
-from .import_ import ImportDataForm, ImportIdentitiesForm
-from .export import ExportDataForm, ExportDomainsForm, ExportIdentitiesForm
-
-__all__ = [
- 'DomainFormGeneral', 'DomainFormOptions', 'DomainForm',
- 'AccountFormGeneral', 'AccountFormMail', 'AccountPermissionsForm',
- 'AccountForm', 'AliasForm', 'ImportDataForm', 'ImportIdentitiesForm',
- 'ExportDataForm', 'ExportDomainsForm', 'ExportIdentitiesForm',
- 'ForwardForm', 'DomainWizard', 'AccountWizard'
-]
diff --git a/modoboa/extensions/admin/forms/account.py b/modoboa/extensions/admin/forms/account.py
deleted file mode 100644
index 3d929f697..000000000
--- a/modoboa/extensions/admin/forms/account.py
+++ /dev/null
@@ -1,478 +0,0 @@
-"""Forms related to accounts management."""
-
-from collections import OrderedDict
-
-from django import forms
-from django.core.urlresolvers import reverse
-from django.http import QueryDict
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.core.models import User
-from modoboa.extensions.admin.models import (
- Domain, Mailbox, Alias
-)
-from modoboa.lib import events, parameters
-from modoboa.lib.email_utils import split_mailbox
-from modoboa.lib.exceptions import PermDeniedException, Conflict, NotFound
-from modoboa.lib.form_utils import (
- DomainNameField, DynamicForm, TabForms, WizardForm
-)
-from modoboa.lib.permissions import get_account_roles
-from modoboa.lib.web_utils import render_to_json_response
-
-
-class AccountFormGeneral(forms.ModelForm):
- username = forms.CharField(
- label=ugettext_lazy("Username"),
- help_text=ugettext_lazy(
- "The user's name. Must be a valid e-mail address for simple users "
- "or administrators with a mailbox."
- )
- )
- role = forms.ChoiceField(
- label=ugettext_lazy("Role"),
- choices=[('', ugettext_lazy("Choose"))],
- help_text=ugettext_lazy("What level of permission this user will have")
- )
- password1 = forms.CharField(
- label=ugettext_lazy("Password"), widget=forms.widgets.PasswordInput
- )
- password2 = forms.CharField(
- label=ugettext_lazy("Confirmation"),
- widget=forms.widgets.PasswordInput,
- help_text=ugettext_lazy(
- "Enter the same password as above, for verification."
- )
- )
-
- class Meta:
- model = User
- fields = ("username", "first_name", "last_name", "role", "is_active")
-
- def __init__(self, user, *args, **kwargs):
- super(AccountFormGeneral, self).__init__(*args, **kwargs)
- self.fields = OrderedDict(
- (key, self.fields[key]) for key in
- ['role', 'username', 'first_name', 'last_name', 'password1',
- 'password2', 'is_active']
- )
- self.fields["is_active"].label = _("Enabled")
- self.user = user
- if user.group == "DomainAdmins":
- self.fields["role"] = forms.CharField(
- label="",
- widget=forms.HiddenInput(attrs={"class": "form-control"}),
- required=False
- )
- else:
- self.fields["role"].choices = [('', ugettext_lazy("Choose"))]
- self.fields["role"].choices += \
- get_account_roles(user, kwargs['instance']) \
- if 'instance' in kwargs else get_account_roles(user)
-
- if "instance" in kwargs:
- account = kwargs["instance"]
- domain_disabled = account.mailbox_set.count() and \
- not account.mailbox_set.all()[0].domain.enabled
- if domain_disabled:
- self.fields["is_active"].widget.attrs['disabled'] = "disabled"
- if args:
- if args[0].get("password1", "") == "" \
- and args[0].get("password2", "") == "":
- self.fields["password1"].required = False
- self.fields["password2"].required = False
- if domain_disabled:
- del self.fields["is_active"]
- self.fields["role"].initial = account.group
- if not account.is_local \
- and parameters.get_admin(
- "LDAP_AUTH_METHOD", app="core") == "directbind":
- del self.fields["password1"]
- del self.fields["password2"]
-
- def domain_is_disabled(self):
- """Little shortcut to get the domain's state.
-
- We need this information inside a template and the form is the
- only object available...
-
- """
- if not self.instance.mailbox_set.count():
- return False
- return not self.instance.mailbox_set.all()[0].domain.enabled
-
- def clean_role(self):
- if self.user.group == "DomainAdmins":
- if self.instance == self.user:
- return "DomainAdmins"
- return "SimpleUsers"
- return self.cleaned_data["role"]
-
- def clean_username(self):
- from django.core.validators import validate_email
- if "role" not in self.cleaned_data:
- return self.cleaned_data["username"]
- if self.cleaned_data["role"] != "SimpleUsers":
- return self.cleaned_data["username"]
- uname = self.cleaned_data["username"].lower()
- validate_email(uname)
- return uname
-
- def clean_password2(self):
- password1 = self.cleaned_data.get("password1", "")
- password2 = self.cleaned_data["password2"]
- if password1 != password2:
- raise forms.ValidationError(
- _("The two password fields didn't match."))
- return password2
-
- def save(self, commit=True):
- account = super(AccountFormGeneral, self).save(commit=False)
- if self.user == account and not self.cleaned_data["is_active"]:
- raise PermDeniedException(_("You can't disable your own account"))
- if commit:
- if "password1" in self.cleaned_data \
- and self.cleaned_data["password1"] != "":
- account.set_password(self.cleaned_data["password1"])
- account.save()
- account.set_role(self.cleaned_data["role"])
- return account
-
-
-class AccountFormMail(forms.Form, DynamicForm):
-
- """Form to handle mail part."""
-
- email = forms.EmailField(label=ugettext_lazy("E-mail"), required=False)
- quota = forms.IntegerField(
- label=ugettext_lazy("Quota"),
- required=False,
- help_text=_("Quota in MB for this mailbox. Define a custom value or "
- "use domain's default one. Leave empty to define an "
- "unlimited value (not allowed for domain "
- "administrators)."),
- widget=forms.widgets.TextInput(attrs={"class": "form-control"})
- )
- quota_act = forms.BooleanField(required=False)
- aliases = forms.EmailField(
- label=ugettext_lazy("Alias(es)"),
- required=False,
- help_text=ugettext_lazy(
- "Alias(es) of this mailbox. Indicate only one address per input, "
- "press ENTER to add a new input. Use the '*' character to create "
- "a 'catchall' alias (ex: *@domain.tld)."
- )
- )
-
- def __init__(self, *args, **kwargs):
- if "instance" in kwargs:
- self.mb = kwargs["instance"]
- del kwargs["instance"]
- else:
- self.mb = None
- super(AccountFormMail, self).__init__(*args, **kwargs)
- self.field_widths = {
- "quota": 3
- }
- self.extra_fields = []
- result = events.raiseQueryEvent('ExtraFormFields', 'mailform', self.mb)
- for fname, field in result:
- self.fields[fname] = field
- self.extra_fields.append(fname)
- if self.mb is not None:
- self.fields["email"].required = True
- cpt = 1
- for alias in self.mb.alias_set.all():
- if len(alias.get_recipients()) >= 2:
- continue
- name = "aliases_%d" % cpt
- self._create_field(forms.EmailField, name, alias.full_address)
- cpt += 1
- self.fields["email"].initial = self.mb.full_address
- self.fields["quota_act"].initial = self.mb.use_domain_quota
- if not self.mb.use_domain_quota and self.mb.quota:
- self.fields["quota"].initial = self.mb.quota
- else:
- self.fields["quota_act"].initial = True
-
- if len(args) and isinstance(args[0], QueryDict):
- self._load_from_qdict(args[0], "aliases", forms.EmailField)
-
- def clean_email(self):
- """Ensure lower case emails"""
- return self.cleaned_data["email"].lower()
-
- def clean(self):
- """Custom fields validation.
-
- Check if quota is >= 0 only when the domain value is not used.
- """
- super(AccountFormMail, self).clean()
- if not self.cleaned_data["quota_act"] \
- and self.cleaned_data['quota'] is not None:
- if self.cleaned_data["quota"] < 0:
- self.add_error("quota", _("Must be a positive integer"))
- return self.cleaned_data
-
- def create_mailbox(self, user, account):
- """Create a mailbox associated to :kw:`account`."""
- locpart, domname = split_mailbox(self.cleaned_data["email"])
- try:
- domain = Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- raise NotFound(_("Domain does not exist"))
- if not user.can_access(domain):
- raise PermDeniedException
- try:
- Mailbox.objects.get(address=locpart, domain=domain)
- except Mailbox.DoesNotExist:
- pass
- else:
- raise Conflict(
- _("Mailbox %s already exists" % self.cleaned_data["email"])
- )
- events.raiseEvent("CanCreate", user, "mailboxes")
- self.mb = Mailbox(address=locpart, domain=domain, user=account,
- use_domain_quota=self.cleaned_data["quota_act"])
- self.mb.set_quota(self.cleaned_data["quota"],
- user.has_perm("admin.add_domain"))
- self.mb.save(creator=user)
-
- def update_mailbox(self, user, account):
- newaddress = None
- if self.cleaned_data["email"] != self.mb.full_address:
- newaddress = self.cleaned_data["email"]
- elif (account.group == "SimpleUsers" and
- account.username != self.mb.full_address):
- newaddress = account.username
- if newaddress is not None:
- self.mb.old_full_address = self.mb.full_address
- local_part, domname = split_mailbox(newaddress)
- try:
- domain = Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- raise NotFound(_("Domain does not exist"))
- if not user.can_access(domain):
- raise PermDeniedException
- self.mb.rename(local_part, domain)
-
- self.mb.use_domain_quota = self.cleaned_data["quota_act"]
- override_rules = True \
- if not self.mb.quota or user.has_perm("admin.add_domain") \
- else False
- self.mb.set_quota(self.cleaned_data["quota"], override_rules)
- self.mb.save()
- events.raiseEvent('MailboxModified', self.mb)
-
- def _update_aliases(self, user, account):
- """Update mailbox aliases."""
- aliases = []
- for name, value in self.cleaned_data.iteritems():
- if not name.startswith("aliases"):
- continue
- if value == "":
- continue
- aliases.append(value.lower())
-
- for alias in self.mb.alias_set.all():
- if alias.full_address not in aliases:
- if len(alias.get_recipients()) >= 2:
- continue
- alias.delete()
- else:
- aliases.remove(alias.full_address)
- if not aliases:
- return
- events.raiseEvent(
- "CanCreate", user, "mailbox_aliases", len(aliases)
- )
- for alias in aliases:
- local_part, domname = split_mailbox(alias)
- try:
- self.mb.alias_set.get(address=local_part, domain__name=domname)
- except Alias.DoesNotExist:
- pass
- else:
- continue
- al = Alias(address=local_part, enabled=account.is_active)
- al.domain = Domain.objects.get(name=domname)
- al.save(int_rcpts=[self.mb])
- al.post_create(user)
-
- def save(self, user, account):
- """Save or update account mailbox."""
- if self.cleaned_data["email"] == "":
- return None
-
- if self.cleaned_data["quota_act"]:
- self.cleaned_data["quota"] = None
-
- if not hasattr(self, "mb") or self.mb is None:
- self.create_mailbox(user, account)
- else:
- self.update_mailbox(user, account)
- events.raiseEvent(
- 'SaveExtraFormFields', 'mailform', self.mb, self.cleaned_data
- )
-
- account.email = self.cleaned_data["email"]
- account.save()
-
- self._update_aliases(user, account)
-
- return self.mb
-
-
-class AccountPermissionsForm(forms.Form, DynamicForm):
- domains = DomainNameField(
- label=ugettext_lazy("Domain(s)"),
- required=False,
- help_text=ugettext_lazy("Domain(s) that user administrates")
- )
-
- def __init__(self, *args, **kwargs):
- if "instance" in kwargs:
- self.account = kwargs["instance"]
- del kwargs["instance"]
-
- super(AccountPermissionsForm, self).__init__(*args, **kwargs)
-
- if not hasattr(self, "account") or self.account is None:
- return
- for pos, dom in enumerate(Domain.objects.get_for_admin(self.account)):
- name = "domains_%d" % (pos + 1)
- self._create_field(DomainNameField, name, dom.name)
- if len(args) and isinstance(args[0], QueryDict):
- self._load_from_qdict(args[0], "domains", DomainNameField)
-
- def save(self):
- current_domains = [
- dom.name for dom in Domain.objects.get_for_admin(self.account)
- ]
- for name, value in self.cleaned_data.items():
- if not name.startswith("domains"):
- continue
- if value in ["", None]:
- continue
- if value not in current_domains:
- domain = Domain.objects.get(name=value)
- domain.add_admin(self.account)
-
- for domain in Domain.objects.get_for_admin(self.account):
- if not filter(lambda name: self.cleaned_data[name] == domain.name,
- self.cleaned_data.keys()):
- domain.remove_admin(self.account)
-
-
-class AccountForm(TabForms):
-
- """Account edition form."""
-
- def __init__(self, request, *args, **kwargs):
- self.user = request.user
- self.forms = [
- dict(id="general", title=_("General"),
- formtpl="admin/account_general_form.html",
- cls=AccountFormGeneral,
- new_args=[self.user], mandatory=True),
- dict(id="mail", title=_("Mail"), formtpl="admin/mailform.html",
- cls=AccountFormMail),
- dict(
- id="perms", title=_("Permissions"),
- formtpl="admin/permsform.html",
- cls=AccountPermissionsForm
- )
- ]
- cbargs = [self.user]
- if "instances" in kwargs:
- cbargs += [kwargs["instances"]["general"]]
- self.forms += events.raiseQueryEvent("ExtraAccountForm", *cbargs)
-
- super(AccountForm, self).__init__(request, *args, **kwargs)
-
- def extra_context(self, context):
- account = self.instances["general"]
- context.update({
- 'title': account.username,
- 'formid': 'accountform',
- 'action': reverse("admin:account_change", args=[account.id]),
- })
-
- def check_perms(self, account):
- if account.is_superuser:
- return False
- return self.user.has_perm("admin.add_domain") \
- and account.has_perm("core.add_user")
-
- def _before_is_valid(self, form):
- if form["id"] == "general":
- return True
-
- if hasattr(self, "check_%s" % form["id"]):
- if not getattr(self, "check_%s" % form["id"])(self.account):
- return False
- return True
-
- extra_forms = events.raiseQueryEvent(
- "CheckExtraAccountForm", self.account, form)
- if False in extra_forms:
- return False
- return True
-
- def is_valid(self):
- """Two steps validation.
- """
- self.instances["general"].oldgroup = self.instances["general"].group
- if super(AccountForm, self).is_valid(mandatory_only=True):
- self.account = self.forms[0]["instance"].save()
- return super(AccountForm, self).is_valid(optional_only=True)
- return False
-
- def save(self):
- """Custom save method
-
- As forms interact with each other, it is simpler to make
- custom code to save them.
- """
- events.raiseEvent(
- "AccountModified", self.instances["general"], self.account
- )
- self.forms[1]["instance"].save(self.user, self.account)
- if len(self.forms) <= 2:
- return
- for f in self.forms[2:]:
- f["instance"].save()
-
- def done(self):
- return render_to_json_response(_("Account updated"))
-
-
-class AccountWizard(WizardForm):
-
- """Account creation wizard.
- """
-
- def __init__(self, request):
- super(AccountWizard, self).__init__(request)
- self.add_step(
- AccountFormGeneral, _("General"), new_args=[request.user]
- )
- self.add_step(
- AccountFormMail, _("Mail"), formtpl="admin/mailform.html"
- )
-
- def extra_context(self, context):
- context.update({
- 'title': _("New account"),
- 'action': reverse("admin:account_add"),
- 'formid': 'newaccount_form'
- })
-
- def done(self):
- from modoboa.lib.web_utils import render_to_json_response
-
- account = self.first_step.form.save()
- account.post_create(self.request.user)
- mailform = self.steps[1].form
- mailform.save(self.request.user, account)
- return render_to_json_response(_("Account created"))
diff --git a/modoboa/extensions/admin/forms/alias.py b/modoboa/extensions/admin/forms/alias.py
deleted file mode 100644
index 12485eebc..000000000
--- a/modoboa/extensions/admin/forms/alias.py
+++ /dev/null
@@ -1,152 +0,0 @@
-"""Forms related to aliases management."""
-
-from collections import OrderedDict
-
-from django import forms
-from django.http import QueryDict
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.extensions.admin.models import (
- Domain, Mailbox, Alias
-)
-from modoboa.lib.email_utils import split_mailbox
-from modoboa.lib.exceptions import BadRequest, NotFound, Conflict
-from modoboa.lib.form_utils import (
- DynamicForm
-)
-
-
-class AliasForm(forms.ModelForm, DynamicForm):
- email = forms.EmailField(
- label=ugettext_lazy("Email address"),
- help_text=ugettext_lazy(
- "The distribution list address. Use the '*' character to create a "
- "'catchall' address (ex: *@domain.tld)."
- ),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
- recipients = forms.EmailField(
- label=ugettext_lazy("Recipients"), required=False,
- help_text=ugettext_lazy(
- "Mailbox(es) this alias will point to. Indicate only one address "
- "per input, press ENTER to add a new input."
- ),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- class Meta:
- model = Alias
- fields = ("enabled",)
-
- def __init__(self, user, *args, **kwargs):
- self.user = user
- super(AliasForm, self).__init__(*args, **kwargs)
- self.fields = OrderedDict(
- (key, self.fields[key]) for key in
- ['email', 'recipients', 'enabled']
- )
-
- if len(args) and isinstance(args[0], QueryDict):
- if "instance" in kwargs:
- if not kwargs["instance"].domain.enabled:
- del self.fields["enabled"]
- self._load_from_qdict(args[0], "recipients", forms.EmailField)
- elif "instance" in kwargs:
- dlist = kwargs["instance"]
- self.fields["email"].initial = dlist.full_address
- if not dlist.domain.enabled:
- self.fields["enabled"].widget.attrs["disabled"] = "disabled"
- cpt = 1
- for al in dlist.aliases.all():
- name = "recipients_%d" % cpt
- self._create_field(forms.EmailField, name, al.full_address, 2)
- cpt += 1
- for mb in dlist.mboxes.all():
- name = "recipients_%d" % (cpt)
- self._create_field(forms.EmailField, name, mb.full_address, 2)
- cpt += 1
- for addr in dlist.extmboxes.split(','):
- if addr == "":
- continue
- name = "recipients_%d" % (cpt)
- self._create_field(forms.EmailField, name, addr, 2)
- cpt += 1
-
- def clean_email(self):
- localpart, domname = split_mailbox(self.cleaned_data["email"])
- try:
- domain = Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- raise forms.ValidationError(_("Domain does not exist"))
- if not self.user.can_access(domain):
- raise forms.ValidationError(
- _("You don't have access to this domain")
- )
- return self.cleaned_data["email"].lower()
-
- def set_recipients(self):
- """Recipients dispatching
-
- We make a difference between 'local' recipients (the ones hosted
- by Modoboa) and 'external' recipients.
- """
- self.ext_rcpts = []
- self.int_rcpts = []
- total = 0
-
- for k, v in self.cleaned_data.items():
- if not k.startswith("recipients"):
- continue
- if v == "":
- continue
- local_part, domname = split_mailbox(v)
- if domname is None:
- raise BadRequest(
- u"%s %s" % (_("Invalid mailbox"), v)
- )
- try:
- domain = Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- domain = None
- if domain is not None:
- try:
- rcpt = Alias.objects.get(domain=domain, address=local_part)
- if rcpt.full_address == self.cleaned_data["email"]:
- rcpt = None
- except Alias.DoesNotExist:
- rcpt = None
- if rcpt is None:
- try:
- rcpt = Mailbox.objects.get(
- domain=domain, address=local_part)
- except Mailbox.DoesNotExist:
- raise NotFound(
- _("Local recipient %s not found" % v)
- )
- if rcpt in self.int_rcpts:
- raise Conflict(
- _("Recipient %s already present" % v)
- )
- self.int_rcpts += [rcpt]
- total += 1
- continue
-
- if v in self.ext_rcpts:
- raise Conflict(
- _("Recipient %s already present" % v)
- )
- self.ext_rcpts += [v]
- total += 1
-
- if total == 0:
- raise BadRequest(_("No recipient defined"))
-
- def save(self, commit=True):
- alias = super(AliasForm, self).save(commit=False)
- localpart, domname = split_mailbox(self.cleaned_data["email"])
- alias.address = localpart
- alias.domain = Domain.objects.get(name=domname)
- if commit:
- alias.save(int_rcpts=self.int_rcpts, ext_rcpts=self.ext_rcpts)
- self.save_m2m()
- return alias
diff --git a/modoboa/extensions/admin/forms/domain.py b/modoboa/extensions/admin/forms/domain.py
deleted file mode 100644
index 8fc8afb15..000000000
--- a/modoboa/extensions/admin/forms/domain.py
+++ /dev/null
@@ -1,362 +0,0 @@
-"""Forms related to domains management."""
-
-from django import forms
-from django.core.urlresolvers import reverse
-from django.http import QueryDict
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.core.models import User
-from modoboa.extensions.admin.lib import check_if_domain_exists
-from modoboa.extensions.admin.models import (
- Domain, DomainAlias, Mailbox, Alias, Quota
-)
-from modoboa.lib import events, parameters
-from modoboa.lib.exceptions import ModoboaException, Conflict
-from modoboa.lib.form_utils import (
- DomainNameField, YesNoField, WizardForm, DynamicForm, TabForms
-)
-from modoboa.lib.web_utils import render_to_json_response
-
-
-class DomainFormGeneral(forms.ModelForm, DynamicForm):
- quota = forms.IntegerField(
- label=ugettext_lazy("Quota"),
- required=False,
- help_text=ugettext_lazy(
- "Default quota in MB applied to mailboxes. Leave empty to use the "
- "default value."
- )
- )
- aliases = DomainNameField(
- label=ugettext_lazy("Alias(es)"),
- required=False,
- help_text=ugettext_lazy(
- "Alias(es) of this domain. Indicate only one name per input, "
- "press ENTER to add a new input."
- )
- )
- name = DomainNameField(
- widget=forms.TextInput()
- )
-
- class Meta:
- model = Domain
- fields = ("name", "quota", "aliases", "enabled")
-
- def __init__(self, *args, **kwargs):
- self.oldname = None
- if "instance" in kwargs:
- self.oldname = kwargs["instance"].name
- super(DomainFormGeneral, self).__init__(*args, **kwargs)
-
- self.field_widths = {
- "quota": 3
- }
-
- if len(args) and isinstance(args[0], QueryDict):
- self._load_from_qdict(args[0], "aliases", DomainNameField)
- elif "instance" in kwargs:
- d = kwargs["instance"]
- for pos, dalias in enumerate(d.domainalias_set.all()):
- name = "aliases_%d" % (pos + 1)
- self._create_field(forms.CharField, name, dalias.name, 3)
-
- def clean_quota(self):
- if self.cleaned_data['quota'] is None:
- return int(parameters.get_admin('DEFAULT_DOMAIN_QUOTA'))
- if self.cleaned_data['quota'] < 0:
- raise forms.ValidationError(_("Must be a positive integer"))
- return self.cleaned_data['quota']
-
- def clean(self):
- """Custom fields validation.
-
- We want to prevent duplicate names between domains and domain
- aliases. Extensions have the possibility to declare other
- objects (see *CheckDomainName* event).
-
- The validation way is not very smart...
- """
- super(DomainFormGeneral, self).clean()
- cleaned_data = self.cleaned_data
- name = cleaned_data["name"]
- label = check_if_domain_exists(name, [(DomainAlias, _('domain alias'))])
- if label is not None:
- self.add_error(
- "name", _("A %s with this name already exists") % unicode(label)
- )
- for k in cleaned_data.keys():
- if not k.startswith("aliases"):
- continue
- if cleaned_data[k] == "":
- del cleaned_data[k]
- continue
- if cleaned_data[k] == name:
- self._errors[k] = self.error_class(
- [_("A %s with this name already exists") % _("domain")]
- )
- del cleaned_data[k]
- continue
- label = check_if_domain_exists(
- cleaned_data[k], [(Domain, _("domain"))])
- if label is not None:
- self.add_error(
- k, _("A %s with this name already exists") % unicode(label))
- return cleaned_data
-
- def update_mailbox_quotas(self, domain):
- """Update all quota records associated to this domain.
-
- This method must be called only when a domain gets renamed. As
- the primary key used for a quota is an email address, rename a
- domain will change all associated email addresses, so it will
- change the primary keys used for quotas. The consequence is we
- can't issue regular UPDATE queries using the .save() method of
- a Quota instance (it will trigger an INSERT as the primary key
- has changed).
-
- So, we use this ugly hack to bypass this behaviour. It is not
- perfomant at all as it will generate one query per quota
- record to update.
- """
- for q in Quota.objects.filter(username__contains="@%s" % self.oldname):
- username = q.username.replace(
- '@%s' % self.oldname, '@%s' % domain.name)
- newq = Quota.objects.create(
- username=username, bytes=q.bytes, messages=q.messages)
- q.delete()
-
- def save(self, user, commit=True, domalias_post_create=False):
- """Custom save method
-
- Updating a domain may have consequences on other objects
- (domain alias, mailbox, quota). The most tricky part concerns
- quotas update.
-
- """
- d = super(DomainFormGeneral, self).save(commit=False)
- if commit:
- old_mail_homes = None
- if self.oldname is not None and d.name != self.oldname:
- d.name = self.oldname
- old_mail_homes = \
- dict((mb.id, mb.mail_home) for mb in d.mailbox_set.all())
- d.name = self.cleaned_data['name']
- d.save()
- Mailbox.objects.filter(domain=d, use_domain_quota=True) \
- .update(quota=d.quota)
- aliases = []
- for k, v in self.cleaned_data.iteritems():
- if not k.startswith("aliases"):
- continue
- if v in ["", None]:
- continue
- aliases.append(v)
- for dalias in d.domainalias_set.all():
- if dalias.name not in aliases:
- dalias.delete()
- else:
- aliases.remove(dalias.name)
- if aliases:
- events.raiseEvent(
- "CanCreate", user, "domain_aliases", len(aliases))
- for alias in aliases:
- try:
- d.domainalias_set.get(name=alias)
- except DomainAlias.DoesNotExist:
- pass
- else:
- continue
- al = DomainAlias(name=alias, target=d, enabled=d.enabled)
- al.save(creator=user) if domalias_post_create else al.save()
-
- if old_mail_homes is not None:
- self.update_mailbox_quotas(d)
- for mb in d.mailbox_set.all():
- mb.rename_dir(old_mail_homes[mb.id])
-
- return d
-
-
-class DomainFormOptions(forms.Form):
- create_dom_admin = YesNoField(
- label=ugettext_lazy("Create a domain administrator"),
- initial="no",
- help_text=ugettext_lazy(
- "Automatically create an administrator for this domain"
- )
- )
-
- dom_admin_username = forms.CharField(
- label=ugettext_lazy("Name"),
- initial="admin",
- help_text=ugettext_lazy(
- "The administrator's name. Don't include the domain's name here, "
- "it will be automatically appended."
- ),
- required=False
- )
-
- create_aliases = YesNoField(
- label=ugettext_lazy("Create aliases"),
- initial="yes",
- help_text=ugettext_lazy(
- "Automatically create standard aliases for this domain"
- ),
- required=False
- )
-
- def __init__(self, user, *args, **kwargs):
- super(DomainFormOptions, self).__init__(*args, **kwargs)
- result = events.raiseQueryEvent('UserCanSetRole', user, 'DomainAdmins')
- if False in result:
- self.fields = {}
- return
- if args:
- if args[0].get("create_dom_admin", "no") == "yes":
- self.fields["dom_admin_username"].required = True
- self.fields["create_aliases"].required = True
-
- def clean_dom_admin_username(self):
- """Ensure admin username is an email address."""
- if '@' in self.cleaned_data["dom_admin_username"]:
- raise forms.ValidationError(_("Invalid format"))
- return self.cleaned_data["dom_admin_username"]
-
- def save(self, user, domain):
- if not self.fields:
- return
- if self.cleaned_data["create_dom_admin"] == "no":
- return
- username = "%s@%s" % (
- self.cleaned_data["dom_admin_username"], domain.name)
- try:
- da = User.objects.get(username=username)
- except User.DoesNotExist:
- pass
- else:
- raise Conflict(_("User '%s' already exists" % username))
- events.raiseEvent("CanCreate", user, "mailboxes")
- da = User(username=username, email=username, is_active=True)
- da.set_password("password")
- da.save()
- da.set_role("DomainAdmins")
- da.post_create(user)
- mb = Mailbox(
- address=self.cleaned_data["dom_admin_username"], domain=domain,
- user=da, use_domain_quota=True
- )
- mb.set_quota(override_rules=user.has_perm("admin.change_domain"))
- mb.save(creator=user)
-
- if self.cleaned_data["create_aliases"] == "yes":
- events.raiseEvent("CanCreate", user, "mailbox_aliases")
- alias = Alias(address="postmaster", domain=domain, enabled=True)
- alias.save(int_rcpts=[mb])
- alias.post_create(user)
-
- domain.add_admin(da)
-
-
-class DomainForm(TabForms):
-
- """Domain edition form."""
-
- template_name = "admin/editdomainform.html"
-
- def __init__(self, request, *args, **kwargs):
- self.user = request.user
- self.forms = []
- if self.user.has_perm("admin.change_domain"):
- self.forms.append({
- "id": "general",
- "title": _("General"),
- "formtpl": "admin/domain_general_form.html",
- "cls": DomainFormGeneral,
- "mandatory": True
- })
-
- cbargs = [self.user]
- if "instances" in kwargs:
- cbargs += [kwargs["instances"]["general"]]
- self.forms += events.raiseQueryEvent("ExtraDomainForm", *cbargs)
- if not self.forms:
- self.active_id = "admins"
- super(DomainForm, self).__init__(request, *args, **kwargs)
-
- def extra_context(self, context):
- domain = self.instances["general"]
- domadmins = [u for u in domain.admins
- if self.request.user.can_access(u) and not u.is_superuser]
- if not self.request.user.is_superuser:
- domadmins = [u for u in domadmins if u.group == "DomainAdmins"]
- context.update({
- "title": domain.name,
- "action": reverse("admin:domain_change", args=[domain.pk]),
- "formid": "domform",
- "domain": domain,
- "domadmins": domadmins
- })
-
- def is_valid(self):
- """Custom validation.
-
- We just save the current name before it is potentially
- modified.
-
- """
- self.instances["general"].oldname = self.instances["general"].name
- return super(DomainForm, self).is_valid()
-
- def save(self):
- """Custom save method.
-
- As forms interact with each other, it is easier to make custom
- code to save them.
- """
- self.forms[0]['instance'].save(
- self.request.user, domalias_post_create=True
- )
- for f in self.forms[1:]:
- f["instance"].save(self.request.user)
-
- def done(self):
- events.raiseEvent("DomainModified", self.instances["general"])
- return render_to_json_response(_("Domain modified"))
-
-
-class DomainWizard(WizardForm):
-
- """Domain creation wizard.
- """
-
- def __init__(self, request):
- super(DomainWizard, self).__init__(request)
- self.add_step(
- DomainFormGeneral, _("General"),
- formtpl="admin/domain_general_form.html"
- )
- self.add_step(
- DomainFormOptions, _("Options"),
- formtpl="admin/domain_options_form.html",
- new_args=[self.request.user]
- )
-
- def extra_context(self, context):
- context.update({
- "title": _("New domain"),
- "action": reverse("admin:domain_add"),
- "formid": "domform"
- })
-
- def done(self):
- genform = self.first_step.form
- domain = genform.save(self.request.user)
- domain.post_create(self.request.user)
- try:
- self.steps[1].form.save(self.request.user, domain)
- except ModoboaException:
- from django.db import transaction
- transaction.rollback()
- raise
- return render_to_json_response(_("Domain created"))
diff --git a/modoboa/extensions/admin/forms/export.py b/modoboa/extensions/admin/forms/export.py
deleted file mode 100644
index f1f8a868b..000000000
--- a/modoboa/extensions/admin/forms/export.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from django import forms
-from django.utils.translation import ugettext_lazy
-
-
-class ExportDataForm(forms.Form):
- filename = forms.CharField(
- label=ugettext_lazy("File name"),
- max_length=100,
- required=False,
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
- sepchar = forms.CharField(
- label=ugettext_lazy("Separator"),
- max_length=1,
- required=False,
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- def __init__(self, *args, **kwargs):
- super(ExportDataForm, self).__init__(*args, **kwargs)
- self.fields["sepchar"].widget.attrs = {"class": "col-md-1 form-control"}
-
- def clean_sepchar(self):
- if self.cleaned_data["sepchar"] == "":
- return ";"
- return str(self.cleaned_data["sepchar"])
-
- def clean_filename(self):
- if self.cleaned_data["filename"] == "":
- return self.fields["filename"].initial
- return str(self.cleaned_data["filename"])
-
-
-class ExportDomainsForm(ExportDataForm):
-
- def __init__(self, *args, **kwargs):
- super(ExportDomainsForm, self).__init__(*args, **kwargs)
- self.fields["filename"].initial = "modoboa-domains.csv"
-
-
-class ExportIdentitiesForm(ExportDataForm):
-
- def __init__(self, *args, **kwargs):
- super(ExportIdentitiesForm, self).__init__(*args, **kwargs)
- self.fields["filename"].initial = "modoboa-identities.csv"
diff --git a/modoboa/extensions/admin/forms/forward.py b/modoboa/extensions/admin/forms/forward.py
deleted file mode 100644
index c4d1e4a7b..000000000
--- a/modoboa/extensions/admin/forms/forward.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""Forms related to forwards management."""
-
-from django import forms
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.extensions.admin.models import (
- Domain
-)
-from modoboa.lib.email_utils import split_mailbox
-from modoboa.lib.exceptions import BadRequest, PermDeniedException
-
-
-class ForwardForm(forms.Form):
- dest = forms.CharField(
- label=ugettext_lazy("Recipient(s)"),
- widget=forms.Textarea(attrs={"class": "form-control"}),
- required=False,
- help_text=ugettext_lazy(
- "Indicate one or more recipients separated by a ','")
- )
- keepcopies = forms.BooleanField(
- label=ugettext_lazy("Keep local copies"),
- required=False,
- help_text=ugettext_lazy(
- "Forward messages and store copies into your local mailbox")
- )
-
- def parse_dest(self):
- self.dests = []
- rawdata = self.cleaned_data["dest"].strip()
- if rawdata == "":
- return
- for d in rawdata.split(","):
- local_part, domname = split_mailbox(d)
- if not local_part or not domname or not len(domname):
- raise BadRequest("Invalid mailbox syntax for %s" % d)
- try:
- Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- self.dests += [d]
- else:
- raise PermDeniedException(
- _("You can't define a forward to a local destination. "
- "Please ask your administrator to create an alias "
- "instead.")
- )
diff --git a/modoboa/extensions/admin/forms/import_.py b/modoboa/extensions/admin/forms/import_.py
deleted file mode 100644
index 0091e4ba8..000000000
--- a/modoboa/extensions/admin/forms/import_.py
+++ /dev/null
@@ -1,43 +0,0 @@
-"""Forms related to import operations."""
-
-from django import forms
-from django.utils.translation import ugettext_lazy
-
-
-class ImportDataForm(forms.Form):
-
- """Base form to import objects."""
-
- sourcefile = forms.FileField(label=ugettext_lazy("Select a file"))
- sepchar = forms.CharField(
- label=ugettext_lazy("Separator"),
- max_length=1,
- required=False,
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
- continue_if_exists = forms.BooleanField(
- label=ugettext_lazy("Continue on error"), required=False,
- help_text=ugettext_lazy("Don't treat duplicated objects as error")
- )
-
- def __init__(self, *args, **kwargs):
- super(ImportDataForm, self).__init__(*args, **kwargs)
- self.fields["sepchar"].widget.attrs = {"class": "col-md-1 form-control"}
-
- def clean_sepchar(self):
- if self.cleaned_data["sepchar"] == "":
- return ";"
- return str(self.cleaned_data["sepchar"])
-
-
-class ImportIdentitiesForm(ImportDataForm):
-
- """A form to import identities."""
-
- crypt_password = forms.BooleanField(
- label=ugettext_lazy("Crypt passwords"), required=False,
- help_text=ugettext_lazy(
- "Check this option if passwords contained in your file "
- "are not crypted"
- )
- )
diff --git a/modoboa/extensions/admin/lib.py b/modoboa/extensions/admin/lib.py
deleted file mode 100644
index 9ba1e9585..000000000
--- a/modoboa/extensions/admin/lib.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# coding: utf-8
-from functools import wraps
-from itertools import chain
-from django.db.models import Q
-from django.contrib.contenttypes.models import ContentType
-from django.utils.translation import ugettext as _
-from modoboa.core.models import User
-from modoboa.lib import events
-from modoboa.lib.exceptions import PermDeniedException
-from modoboa.lib.email_utils import split_mailbox
-from modoboa.extensions.admin.models import (
- Domain, Alias
-)
-
-
-def needs_mailbox():
- """Check if the current user owns at least one mailbox
-
- Some applications (the webmail for example) need a mailbox to
- work.
- """
- def decorator(f):
- @wraps(f)
- def wrapped_f(request, *args, **kwargs):
- if request.user.mailbox_set.count():
- return f(request, *args, **kwargs)
- raise PermDeniedException(_("A mailbox is required"))
- return wrapped_f
- return decorator
-
-
-def get_identities(user, searchquery=None, idtfilter=None, grpfilter=None):
- """Return all the identities owned by a user.
-
- :param user: the desired user
- :param str searchquery: search pattern
- :param list idtfilter: identity type filters
- :param list grpfilter: group names filters
- :return: a queryset
- """
- accounts = []
- if idtfilter is None or not idtfilter or idtfilter == "account":
- ids = user.objectaccess_set \
- .filter(content_type=ContentType.objects.get_for_model(user)) \
- .values_list('object_id', flat=True)
- q = Q(pk__in=ids)
- if searchquery is not None:
- q &= Q(username__icontains=searchquery) \
- | Q(email__icontains=searchquery)
- if grpfilter is not None and grpfilter:
- if grpfilter == "SuperAdmins":
- q &= Q(is_superuser=True)
- else:
- q &= Q(groups__name=grpfilter)
- accounts = User.objects.select_related().filter(q)
-
- aliases = []
- if idtfilter is None or not idtfilter \
- or (idtfilter in ["alias", "forward", "dlist"]):
- alct = ContentType.objects.get_for_model(Alias)
- ids = user.objectaccess_set.filter(content_type=alct) \
- .values_list('object_id', flat=True)
- q = Q(pk__in=ids)
- if searchquery is not None:
- if '@' in searchquery:
- local_part, domname = split_mailbox(searchquery)
- if local_part:
- q &= Q(address__icontains=local_part)
- if domname:
- q &= Q(domain__name__icontains=domname)
- else:
- q &= Q(address__icontains=searchquery) | \
- Q(domain__name__icontains=searchquery)
- aliases = Alias.objects.select_related().filter(q)
- if idtfilter is not None and idtfilter:
- aliases = [al for al in aliases if al.type == idtfilter]
- return chain(accounts, aliases)
-
-
-def get_domains(user, domfilter=None, searchquery=None, **extrafilters):
- """Return all the domains the user can access.
-
- :param ``User`` user: user object
- :param str searchquery: filter
- :rtype: list
- :return: a list of domains and/or relay domains
- """
- domains = []
- if domfilter is None or not domfilter or domfilter == 'domain':
- domains = Domain.objects.get_for_admin(user)
- if searchquery is not None:
- q = Q(name__contains=searchquery)
- q |= Q(domainalias__name__contains=searchquery)
- domains = domains.filter(q).distinct()
- extra_domain_entries = events.raiseQueryEvent(
- 'ExtraDomainEntries', user, domfilter, searchquery, **extrafilters
- )
- return chain(domains, extra_domain_entries)
-
-
-def check_if_domain_exists(name, extra_checks=None):
- """Check if a domain already exists.
-
- We not only look for domains, we also look for every object that
- could conflict with a domain (domain alias, etc.)
-
- """
- dtypes = events.raiseQueryEvent('CheckDomainName')
- if extra_checks is not None:
- dtypes = extra_checks + dtypes
- for dtype, label in dtypes:
- if dtype.objects.filter(name=name).exists():
- return label
- return None
diff --git a/modoboa/extensions/admin/management/__init__.py b/modoboa/extensions/admin/management/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/admin/management/commands/__init__.py b/modoboa/extensions/admin/management/commands/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/admin/management/commands/handle_mailbox_operations.py b/modoboa/extensions/admin/management/commands/handle_mailbox_operations.py
deleted file mode 100644
index b0cea9d46..000000000
--- a/modoboa/extensions/admin/management/commands/handle_mailbox_operations.py
+++ /dev/null
@@ -1,97 +0,0 @@
-
-import logging
-from optparse import make_option
-import os
-
-from django.core.management.base import BaseCommand
-
-from modoboa.core.management.commands import CloseConnectionMixin
-from modoboa.lib import parameters
-from modoboa.lib.sysutils import exec_cmd
-from modoboa.lib.exceptions import InternalError
-from modoboa.extensions.admin.models import MailboxOperation
-
-
-class OperationError(Exception):
- pass
-
-
-class Command(BaseCommand, CloseConnectionMixin):
- help = 'Handles rename and delete operations on mailboxes'
-
- option_list = BaseCommand.option_list + (
- make_option(
- '--pidfile', default='/tmp/handle_mailbox_operations.pid',
- help='Path to the file that will contain the PID of this process'
- ),
- )
-
- def __init__(self, *args, **kwargs):
- super(Command, self).__init__(*args, **kwargs)
- self.logger = logging.getLogger('modoboa.admin')
-
- def rename_mailbox(self, operation):
- if not os.path.exists(operation.argument):
- return
- new_mail_home = operation.mailbox.mail_home
- dirname = os.path.dirname(new_mail_home)
- if not os.path.exists(dirname):
- try:
- os.makedirs(dirname)
- except os.error as e:
- raise OperationError(str(e))
- code, output = exec_cmd(
- "mv %s %s" % (operation.argument, new_mail_home)
- )
- if code:
- raise OperationError(output)
-
- def delete_mailbox(self, operation):
- if not os.path.exists(operation.argument):
- return
- code, output = exec_cmd(
- "rm -r %s" % operation.argument
- )
- if code:
- raise OperationError(output)
-
- def check_pidfile(self, path):
- """Check if this command is already running
-
- :param str path: path to the file containing the PID
- :return: a boolean, True means we can go further
- """
- if os.path.exists(path):
- with open(path) as fp:
- pid = fp.read().strip()
- code, output = exec_cmd(
- "grep handle_mailbox_operations /proc/%s/cmdline" % pid
- )
- if not code:
- return False
- with open(path, 'w') as fp:
- print >> fp, os.getpid()
- return True
-
- def handle(self, *args, **options):
- try:
- if parameters.get_admin("HANDLE_MAILBOXES") == 'no':
- return
- except parameters.NotDefined:
- return
- if not self.check_pidfile(options['pidfile']):
- return
- for ope in MailboxOperation.objects.all():
- try:
- f = getattr(self, '%s_mailbox' % ope.type)
- except AttributeError:
- continue
- try:
- f(ope)
- except (OperationError, InternalError) as e:
- self.logger.critical('%s failed (reason: %s)',
- ope, str(e).encode('utf-8'))
- else:
- self.logger.info('%s succeed', ope)
- ope.delete()
- os.unlink(options['pidfile'])
diff --git a/modoboa/extensions/admin/migrations/0001_initial.py b/modoboa/extensions/admin/migrations/0001_initial.py
deleted file mode 100644
index ed6048142..000000000
--- a/modoboa/extensions/admin/migrations/0001_initial.py
+++ /dev/null
@@ -1,161 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-from django.conf import settings
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Alias',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('address', models.CharField(help_text="The alias address (without the domain part). For a 'catch-all' address, just enter an * character.", max_length=254, verbose_name='address')),
- ('extmboxes', models.TextField(blank=True)),
- ('enabled', models.BooleanField(default=True, help_text='Check to activate this alias', verbose_name='enabled')),
- ('aliases', models.ManyToManyField(help_text='The aliases this alias points to', to='admin.Alias')),
- ],
- options={
- 'ordering': ['domain__name', 'address'],
- 'permissions': (('view_aliases', 'View aliases'),),
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Domain',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(help_text='The domain name', unique=True, max_length=100, verbose_name='name')),
- ('quota', models.IntegerField()),
- ('enabled', models.BooleanField(default=True, help_text='Check to activate this domain', verbose_name='enabled')),
- ],
- options={
- 'ordering': ['name'],
- 'permissions': (('view_domain', 'View domain'), ('view_domains', 'View domains')),
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='DomainAlias',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(help_text='The alias name', unique=True, max_length=100, verbose_name='name')),
- ('enabled', models.BooleanField(default=True, help_text='Check to activate this alias', verbose_name='enabled')),
- ],
- options={
- 'permissions': (('view_domaliases', 'View domain aliases'),),
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Mailbox',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('address', models.CharField(help_text='Mailbox address (without the @domain.tld part)', max_length=252, verbose_name='address')),
- ('quota', models.PositiveIntegerField()),
- ('use_domain_quota', models.BooleanField(default=False)),
- ],
- options={
- 'permissions': (('view_mailboxes', 'View mailboxes'),),
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='MailboxOperation',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('type', models.CharField(max_length=20, choices=[(b'rename', b'rename'), (b'delete', b'delete')])),
- ('argument', models.TextField()),
- ('mailbox', models.ForeignKey(blank=True, to='admin.Mailbox', null=True)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='ObjectDates',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('creation', models.DateTimeField(auto_now_add=True)),
- ('last_modification', models.DateTimeField(auto_now=True)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Quota',
- fields=[
- ('username', models.EmailField(max_length=254, serialize=False, primary_key=True)),
- ('bytes', models.BigIntegerField(default=0)),
- ('messages', models.IntegerField(default=0)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.AddField(
- model_name='mailbox',
- name='dates',
- field=models.ForeignKey(to='admin.ObjectDates'),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='mailbox',
- name='domain',
- field=models.ForeignKey(to='admin.Domain'),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='mailbox',
- name='user',
- field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='domainalias',
- name='dates',
- field=models.ForeignKey(to='admin.ObjectDates'),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='domainalias',
- name='target',
- field=models.ForeignKey(verbose_name='target', to='admin.Domain', help_text='The domain this alias points to'),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='domain',
- name='dates',
- field=models.ForeignKey(to='admin.ObjectDates'),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='alias',
- name='dates',
- field=models.ForeignKey(to='admin.ObjectDates'),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='alias',
- name='domain',
- field=models.ForeignKey(to='admin.Domain'),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='alias',
- name='mboxes',
- field=models.ManyToManyField(help_text='The mailboxes this alias points to', to='admin.Mailbox', verbose_name='mailboxes'),
- preserve_default=True,
- ),
- migrations.AlterUniqueTogether(
- name='alias',
- unique_together=set([('address', 'domain')]),
- ),
- ]
diff --git a/modoboa/extensions/admin/migrations/__init__.py b/modoboa/extensions/admin/migrations/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/admin/models/__init__.py b/modoboa/extensions/admin/models/__init__.py
deleted file mode 100644
index 641eff9ad..000000000
--- a/modoboa/extensions/admin/models/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from .base import AdminObject
-from .domain import Domain
-from .domain_alias import DomainAlias
-from .mailbox import Mailbox, Quota, MailboxOperation
-from .alias import Alias
-
-__all__ = [
- 'Domain', 'DomainAlias', 'Mailbox', 'Quota', 'Alias',
- 'MailboxOperation', 'AdminObject'
-]
diff --git a/modoboa/extensions/admin/models/alias.py b/modoboa/extensions/admin/models/alias.py
deleted file mode 100644
index 646dab326..000000000
--- a/modoboa/extensions/admin/models/alias.py
+++ /dev/null
@@ -1,210 +0,0 @@
-"""Models related to aliases management."""
-
-from django.db import models
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-import reversion
-
-from .base import AdminObject
-from .domain import Domain
-from .mailbox import Mailbox
-from modoboa.lib.email_utils import split_mailbox
-from modoboa.lib.exceptions import (
- PermDeniedException, BadRequest, Conflict
-)
-
-
-class Alias(AdminObject):
-
- """
- Mailbox alias.
- """
- address = models.CharField(
- ugettext_lazy('address'), max_length=254,
- help_text=ugettext_lazy(
- "The alias address (without the domain part). For a 'catch-all' "
- "address, just enter an * character."
- )
- )
- domain = models.ForeignKey(Domain)
- mboxes = models.ManyToManyField(
- Mailbox, verbose_name=ugettext_lazy('mailboxes'),
- help_text=ugettext_lazy("The mailboxes this alias points to")
- )
- aliases = models.ManyToManyField(
- 'Alias',
- help_text=ugettext_lazy("The aliases this alias points to")
- )
- extmboxes = models.TextField(blank=True)
- enabled = models.BooleanField(
- ugettext_lazy('enabled'),
- help_text=ugettext_lazy("Check to activate this alias"),
- default=True
- )
- _objectname = 'MailboxAlias'
-
- class Meta:
- permissions = (
- ("view_aliases", "View aliases"),
- )
- unique_together = (("address", "domain"),)
- ordering = ["domain__name", "address"]
- app_label = 'admin'
-
- def __unicode__(self):
- return self.full_address
-
- @property
- def full_address(self):
- return "%s@%s" % (self.address, self.domain.name)
-
- @property
- def identity(self):
- return self.full_address
-
- @property
- def name_or_rcpt(self):
- rcpts_count = self.get_recipients_count()
- if not rcpts_count:
- return "---"
- rcpts = self.get_recipients()
- if rcpts_count > 1:
- return "%s, ..." % rcpts[0]
- return rcpts[0]
-
- @property
- def type(self):
- cpt = self.get_recipients_count()
- if cpt > 1:
- return "dlist"
- if self.extmboxes != "":
- return "forward"
- return "alias"
-
- @property
- def tags(self):
- labels = {
- "dlist": _("distribution list"),
- "forward": _("forward"),
- "alias": _("alias")
- }
- altype = self.type
- return [{"name": altype, "label": labels[altype], "type": "idt"}]
-
- def post_create(self, creator):
- from modoboa.lib.permissions import grant_access_to_object
- super(Alias, self).post_create(creator)
- if creator.is_superuser:
- for admin in self.domain.admins:
- grant_access_to_object(admin, self)
-
- def save(self, *args, **kwargs):
- """Custom save method."""
- if 'ext_rcpts' in kwargs:
- self.extmboxes = ",".join(kwargs['ext_rcpts']) \
- if kwargs['ext_rcpts'] else ""
- del kwargs['ext_rcpts']
- if 'int_rcpts' in kwargs:
- int_rcpts = kwargs['int_rcpts']
- del kwargs['int_rcpts']
- else:
- int_rcpts = []
- super(Alias, self).save(*args, **kwargs)
- curaliases = self.aliases.all()
- curmboxes = self.mboxes.all()
- for rcpt in int_rcpts:
- if isinstance(rcpt, Alias):
- if rcpt not in curaliases:
- self.aliases.add(rcpt)
- continue
- if rcpt not in curmboxes:
- self.mboxes.add(rcpt)
- for rcpt in curaliases:
- if rcpt not in int_rcpts:
- self.aliases.remove(rcpt)
- for rcpt in curmboxes:
- if rcpt not in int_rcpts:
- self.mboxes.remove(rcpt)
-
- def get_recipients(self, with_external=True):
- """Return the recipients list.
-
- Internal and external addresses are mixed into a single list.
-
- :param bool with_external: include external addresses or not
- :rtype: list
- :return: a list of addresses
- """
- result = [al.full_address for al in self.aliases.all()]
- result += [mb.full_address for mb in self.mboxes.all()]
- if with_external and self.extmboxes != "":
- result += self.extmboxes.split(',')
- return result
-
- def get_recipients_count(self):
- """Return the number of recipients of this alias.
-
- :rtype: int
- """
- total = 0
- if self.extmboxes != "":
- total += len(self.extmboxes.split(','))
- return total + self.aliases.count() + self.mboxes.count()
-
- def from_csv(self, user, row, expected_elements=5):
- """Create a new alias from a CSV file entry
-
- """
- if len(row) < expected_elements:
- raise BadRequest(_("Invalid line: %s" % row))
- localpart, domname = split_mailbox(row[1].strip())
- try:
- domain = Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- raise BadRequest(_("Domain '%s' does not exist" % domname))
- if not user.can_access(domain):
- raise PermDeniedException
- try:
- Alias.objects.get(address=localpart, domain__name=domain)
- except Alias.DoesNotExist:
- pass
- else:
- raise Conflict
- self.address = localpart
- self.domain = domain
- self.enabled = (row[2].strip() in ["True", "1", "yes", "y"])
- int_rcpts = []
- ext_rcpts = []
- for rcpt in row[3:]:
- rcpt = rcpt.strip()
- if not rcpt:
- continue
- localpart, domname = split_mailbox(rcpt)
- try:
- Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- ext_rcpts += [rcpt]
- continue
- try:
- target = Alias.objects.get(
- domain__name=domname, address=localpart
- )
- if target.full_address == self.full_address:
- target = None
- except Alias.DoesNotExist:
- target = None
- if target is None:
- try:
- target = Mailbox.objects.get(address=localpart,
- domain__name=domname)
- except Mailbox.DoesNotExist:
- raise BadRequest(_("Local recipient %s not found" % rcpt))
- int_rcpts += [target]
- self.save(int_rcpts=int_rcpts, ext_rcpts=ext_rcpts, creator=user)
-
- def to_csv(self, csvwriter):
- row = [self.type, self.full_address.encode("utf-8"), self.enabled]
- row += self.get_recipients()
- csvwriter.writerow(row)
-
-reversion.register(Alias)
diff --git a/modoboa/extensions/admin/models/base.py b/modoboa/extensions/admin/models/base.py
deleted file mode 100644
index c576bdcad..000000000
--- a/modoboa/extensions/admin/models/base.py
+++ /dev/null
@@ -1,81 +0,0 @@
-from django.db import models
-from modoboa.lib import events
-from modoboa.lib.permissions import (
- grant_access_to_object, ungrant_access_to_object
-)
-
-
-class ObjectDates(models.Model):
-
- """Dates recording for admin objects
-
- This table keeps creation and last modification dates for Domains,
- domain aliases, mailboxes and aliases objects.
- """
- creation = models.DateTimeField(auto_now_add=True)
- last_modification = models.DateTimeField(auto_now=True)
-
- class Meta:
- app_label = 'admin'
-
- @staticmethod
- def set_for_object(obj):
- """Initialize or update dates for a given object.
-
- :param obj: an admin object (Domain, Mailbox, etc)
- """
- try:
- dates = getattr(obj, "dates")
- except ObjectDates.DoesNotExist:
- dates = ObjectDates()
- dates.save()
- obj.dates = dates
-
-
-class AdminObject(models.Model):
-
- """Abstract model to support dates
-
- Inherit from this model to automatically add the "dates" feature
- to another model. It defines the appropriate field and handles
- saves.
- """
- dates = models.ForeignKey(ObjectDates)
- _objectname = None
-
- class Meta:
- abstract = True
-
- @property
- def creation(self):
- return self.dates.creation
-
- @property
- def last_modification(self):
- return self.dates.last_modification
-
- @property
- def objectname(self):
- if self._objectname is None:
- return self.__class__.__name__
- return self._objectname
-
- def post_create(self, creator):
- grant_access_to_object(creator, self, is_owner=True)
- events.raiseEvent("%sCreated" % self.objectname, creator, self)
-
- def save(self, *args, **kwargs):
- ObjectDates.set_for_object(self)
- if "creator" in kwargs:
- creator = kwargs["creator"]
- del kwargs["creator"]
- else:
- creator = None
- super(AdminObject, self).save(*args, **kwargs)
- if creator is not None:
- self.post_create(creator)
-
- def delete(self):
- events.raiseEvent("%sDeleted" % self.objectname, self)
- ungrant_access_to_object(self)
- super(AdminObject, self).delete()
diff --git a/modoboa/extensions/admin/models/domain.py b/modoboa/extensions/admin/models/domain.py
deleted file mode 100644
index 8d996def4..000000000
--- a/modoboa/extensions/admin/models/domain.py
+++ /dev/null
@@ -1,185 +0,0 @@
-"""Models related to domains management."""
-
-from django.contrib.contenttypes import generic
-from django.db import models
-from django.db.models.manager import Manager
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-import reversion
-
-from .base import AdminObject
-from modoboa.core.models import User, ObjectAccess
-from modoboa.lib import events, parameters
-from modoboa.lib.exceptions import BadRequest, Conflict
-
-
-class DomainManager(Manager):
-
- def get_for_admin(self, admin):
- """Return the domains belonging to this admin
-
- The result is a ``QuerySet`` object, so this function can be used
- to fill ``ModelChoiceField`` objects.
- """
- if admin.is_superuser:
- return self.get_query_set()
- return self.get_query_set().filter(owners__user=admin)
-
-
-class Domain(AdminObject):
-
- """Mail domain."""
-
- name = models.CharField(ugettext_lazy('name'), max_length=100, unique=True,
- help_text=ugettext_lazy("The domain name"))
- quota = models.IntegerField()
- enabled = models.BooleanField(
- ugettext_lazy('enabled'),
- help_text=ugettext_lazy("Check to activate this domain"),
- default=True
- )
- owners = generic.GenericRelation(ObjectAccess)
-
- objects = DomainManager()
-
- class Meta:
- permissions = (
- ("view_domain", "View domain"),
- ("view_domains", "View domains"),
- )
- ordering = ["name"]
- app_label = 'admin'
-
- @property
- def domainalias_count(self):
- return self.domainalias_set.count()
-
- @property
- def mailbox_count(self):
- return self.mailbox_set.count()
-
- @property
- def mbalias_count(self):
- return self.alias_set.count()
-
- @property
- def identities_count(self):
- """Total number of identities in this domain."""
- return self.mailbox_set.count() + self.alias_set.count()
-
- @property
- def tags(self):
- return [{"name": "domain", "label": _("Domain"), "type": "dom"}]
-
- @property
- def admins(self):
- """Return the domain administrators of this domain
-
- :return: a list of User objects
- """
- return [oa.user for oa in self.owners.filter(user__is_superuser=False)]
-
- @property
- def aliases(self):
- return self.domainalias_set
-
- def add_admin(self, account):
- """Add a new administrator for this domain
-
- :param User account: the administrotor to add
- """
- from modoboa.lib.permissions import grant_access_to_object
- grant_access_to_object(account, self)
- for mb in self.mailbox_set.all():
- if mb.user.has_perm("admin.add_domain"):
- continue
- grant_access_to_object(account, mb)
- grant_access_to_object(account, mb.user)
- for al in self.alias_set.all():
- grant_access_to_object(account, al)
-
- def remove_admin(self, account):
- """Remove an administrator of this domain.
-
- :param User account: administrator to remove
- """
- from modoboa.lib.permissions import \
- ungrant_access_to_object, get_object_owner
-
- if get_object_owner(self) == account:
- events.raiseEvent('DomainOwnershipRemoved', account, self)
- ungrant_access_to_object(self, account)
- for mb in self.mailbox_set.all():
- if mb.user.has_perm("admin.add_domain"):
- continue
- ungrant_access_to_object(mb, account)
- ungrant_access_to_object(mb.user, account)
- for al in self.alias_set.all():
- ungrant_access_to_object(al, account)
-
- def delete(self, fromuser, keepdir=False):
- """Custom delete method.
- """
- from modoboa.lib.permissions import ungrant_access_to_objects
- from .mailbox import Quota
-
- if self.domainalias_set.count():
- events.raiseEvent("DomainAliasDeleted", self.domainalias_set.all())
- ungrant_access_to_objects(self.domainalias_set.all())
- if self.alias_set.count():
- events.raiseEvent("MailboxAliasDeleted", self.alias_set.all())
- ungrant_access_to_objects(self.alias_set.all())
- if parameters.get_admin("AUTO_ACCOUNT_REMOVAL") == "yes":
- for account in User.objects.filter(mailbox__domain__name=self.name):
- account.delete(fromuser, keepdir)
- elif self.mailbox_set.count():
- Quota.objects.filter(username__contains='@%s' % self.name).delete()
- events.raiseEvent("MailboxDeleted", self.mailbox_set.all())
- ungrant_access_to_objects(self.mailbox_set.all())
- super(Domain, self).delete()
-
- def __str__(self):
- return self.name
-
- def from_csv(self, user, row):
- """Create a new domain from a CSV entry.
-
- The expected fields order is the following::
-
- "domain", name, quota, enabled
-
- :param ``core.User`` user: user creating the domain
- :param str row: a list containing domain's definition
- """
- if len(row) < 4:
- raise BadRequest(_("Invalid line"))
- self.name = row[1].strip()
- try:
- Domain.objects.get(name=self.name)
- except Domain.DoesNotExist:
- pass
- else:
- raise Conflict
- try:
- self.quota = int(row[2].strip())
- except ValueError:
- raise BadRequest(
- _("Invalid quota value for domain '%s'" % self.name))
- self.enabled = (row[3].strip() in ["True", "1", "yes", "y"])
- self.save(creator=user)
-
- def to_csv(self, csvwriter):
- csvwriter.writerow(["domain", self.name, self.quota, self.enabled])
- for dalias in self.domainalias_set.all():
- dalias.to_csv(csvwriter)
-
- def post_create(self, creator):
- """Post creation actions.
-
- :param ``User`` creator: user whos created this domain
- """
- super(Domain, self).post_create(creator)
- for domalias in self.domainalias_set.all():
- domalias.post_create(creator)
-
-reversion.register(Domain)
diff --git a/modoboa/extensions/admin/models/domain_alias.py b/modoboa/extensions/admin/models/domain_alias.py
deleted file mode 100644
index ba784a3cb..000000000
--- a/modoboa/extensions/admin/models/domain_alias.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""Models related to domain aliases management."""
-
-from django.db import models
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-import reversion
-
-from .base import AdminObject
-from .domain import Domain
-from modoboa.lib.exceptions import BadRequest, Conflict
-
-
-class DomainAlias(AdminObject):
-
- """Domain aliases."""
-
- name = models.CharField(ugettext_lazy("name"), max_length=100, unique=True,
- help_text=ugettext_lazy("The alias name"))
- target = models.ForeignKey(
- Domain, verbose_name=ugettext_lazy('target'),
- help_text=ugettext_lazy("The domain this alias points to")
- )
- enabled = models.BooleanField(
- ugettext_lazy('enabled'),
- help_text=ugettext_lazy("Check to activate this alias"),
- default=True
- )
-
- class Meta:
- permissions = (
- ("view_domaliases", "View domain aliases"),
- )
- app_label = 'admin'
-
- def __unicode__(self):
- return self.name
-
- def from_csv(self, user, row):
- """Create a domain alias from a CSV row
-
- Expected format: ["domainalias", domain alias name, targeted domain, enabled]
-
- :param user: a ``User`` object
- :param row: a list containing the alias definition
- """
- if len(row) < 4:
- raise BadRequest(_("Invalid line"))
- self.name = row[1].strip()
- for model in [DomainAlias, Domain]:
- try:
- model.objects.get(name=self.name)
- except model.DoesNotExist:
- pass
- else:
- raise Conflict
- domname = row[2].strip()
- try:
- self.target = Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- raise BadRequest(_("Unknown domain %s" % domname))
- self.enabled = row[3].strip() in ["True", "1", "yes", "y"]
- self.save(creator=user)
-
- def to_csv(self, csvwriter):
- """Export a domain alias using CSV format
-
- :param csvwriter: a ``csv.writer`` object
- """
- csvwriter.writerow(["domainalias", self.name,
- self.target.name, self.enabled])
-
-reversion.register(DomainAlias)
diff --git a/modoboa/extensions/admin/models/mailbox.py b/modoboa/extensions/admin/models/mailbox.py
deleted file mode 100644
index fcc46e52c..000000000
--- a/modoboa/extensions/admin/models/mailbox.py
+++ /dev/null
@@ -1,334 +0,0 @@
-"""Models related to mailboxes management."""
-
-import os
-import pwd
-
-from django.contrib.contenttypes.models import ContentType
-from django.db import models
-from django.db.models import Q
-from django.db.models.manager import Manager
-from django.db.models.signals import pre_delete
-from django.dispatch import receiver
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-import reversion
-
-from .base import AdminObject
-from .domain import Domain
-from modoboa.core.models import User
-from modoboa.lib import parameters, events
-from modoboa.lib.exceptions import BadRequest, InternalError
-from modoboa.lib.sysutils import exec_cmd
-
-
-class Quota(models.Model):
-
- """Keeps track of Mailbox current quota."""
-
- username = models.EmailField(primary_key=True, max_length=254)
- bytes = models.BigIntegerField(default=0)
- messages = models.IntegerField(default=0)
-
- class Meta:
- app_label = 'admin'
-
-
-class MailboxManager(Manager):
-
- """Custom manager for Mailbox."""
-
- def get_for_admin(self, admin, squery=None):
- """Return the mailboxes that belong to this admin.
-
- The result will contain the mailboxes defined for each domain that
- user can see.
-
- :param string squery: a search query
- :return: a list of ``Mailbox`` objects
- """
- qf = None
- if squery is not None:
- if '@' in squery:
- parts = squery.split('@')
- addrfilter = '@'.join(parts[:-1])
- domfilter = parts[-1]
- qf = (
- Q(address__contains=addrfilter) &
- Q(domain__name__contains=domfilter)
- )
- else:
- qf = (
- Q(address__contains=squery) |
- Q(domain__name__contains=squery)
- )
- ids = admin.objectaccess_set \
- .filter(content_type=ContentType.objects.get_for_model(Mailbox)) \
- .values_list('object_id', flat=True)
- if qf is not None:
- qf = Q(pk__in=ids) & qf
- else:
- qf = Q(pk__in=ids)
- return self.get_query_set().select_related().filter(qf)
-
-
-class Mailbox(AdminObject):
-
- """User mailbox."""
-
- address = models.CharField(
- ugettext_lazy('address'), max_length=252,
- help_text=ugettext_lazy(
- "Mailbox address (without the @domain.tld part)")
- )
- quota = models.PositiveIntegerField()
- use_domain_quota = models.BooleanField(default=False)
- domain = models.ForeignKey(Domain)
- user = models.ForeignKey(User)
-
- objects = MailboxManager()
-
- class Meta:
- permissions = (
- ("view_mailboxes", "View mailboxes"),
- )
- app_label = 'admin'
-
- def __init__(self, *args, **kwargs):
- super(Mailbox, self).__init__(*args, **kwargs)
- self.__mail_home = None
-
- def __str__(self):
- return self.full_address
-
- def __full_address(self, localpart):
- return "%s@%s" % (localpart, self.domain.name)
-
- @property
- def full_address(self):
- return self.__full_address(self.address)
-
- @property
- def enabled(self):
- return self.user.is_active
-
- @property
- def alias_count(self):
- return self.alias_set.count()
-
- @property
- def mail_home(self):
- """Retrieve the home directory of this mailbox.
-
- The home directory refers to the place on the file system
- where the mailbox data is stored.
-
- We ask dovecot to give us this information because there are
- several patterns to understand and we don't want to implement
- them.
- """
- hm = parameters.get_admin("HANDLE_MAILBOXES", raise_error=False)
- if hm is None or hm == "no":
- return None
- if self.__mail_home is None:
- curuser = pwd.getpwuid(os.getuid()).pw_name
- mbowner = parameters.get_admin("MAILBOXES_OWNER")
- options = {}
- if curuser != mbowner:
- options['sudo_user'] = mbowner
- code, output = exec_cmd(
- "doveadm user %s -f home" % self.full_address, **options
- )
- if code:
- raise InternalError(
- _("Failed to retrieve mailbox location (%s)" % output))
- self.__mail_home = output.strip()
- return self.__mail_home
-
- @property
- def alias_addresses(self):
- """Return all alias address of this mailbox.
-
- :rtype: list of string
- """
- aliases = []
- for alias in self.alias_set.all():
- aliases += [alias.full_address]
- return aliases
-
- @property
- def quota_value(self):
- """Retrieve the ``Quota`` instance associated to this mailbox."""
- if not hasattr(self, "_quota_value"):
- try:
- self._quota_value = Quota.objects.get(
- username=self.full_address)
- except Quota.DoesNotExist:
- return None
- return self._quota_value
-
- @quota_value.setter
- def quota_value(self, instance):
- """Set the ``Quota`` for this mailbox."""
- self._quota_value = instance
-
- def rename_dir(self, old_mail_home):
- hm = parameters.get_admin("HANDLE_MAILBOXES", raise_error=False)
- if hm is None or hm == "no":
- return
- MailboxOperation.objects.create(
- mailbox=self, type='rename', argument=old_mail_home
- )
-
- def rename(self, address, domain):
- """Rename the mailbox.
-
- To update the associated Quota record, we must create a new
- one first, update the foreign key and then we can delete the
- original record!
-
- :param string address: the new mailbox's address (local part)
- :param Domain domain: the new mailbox's domain
-
- """
- old_mail_home = self.mail_home
- old_qvalue = self.quota_value
- self.address = address
- self.domain = domain
- self.quota_value = Quota.objects.create(
- username=self.full_address, bytes=old_qvalue.bytes,
- messages=old_qvalue.messages
- )
- old_qvalue.delete()
- self.rename_dir(old_mail_home)
-
- def delete_dir(self):
- hm = parameters.get_admin("HANDLE_MAILBOXES", raise_error=False)
- if hm is None or hm == "no":
- return
- MailboxOperation.objects.create(type='delete', argument=self.mail_home)
-
- def set_quota(self, value=None, override_rules=False):
- """Set or update quota's value for this mailbox.
-
- A value equal to 0 means the mailbox won't have any quota. The
- following cases allow people to define such behaviour:
- * The domain has no quota
- * :keyword:`override_rules` is True
-
- :param integer value: the quota's value
- :param bool override_rules: allow to override defined quota rules
- """
- if value is None:
- if self.use_domain_quota:
- self.quota = self.domain.quota
- else:
- self.quota = 0
- elif int(value) > self.domain.quota and not override_rules:
- raise BadRequest(
- _("Quota is greater than the allowed domain's limit (%dM)"
- % self.domain.quota)
- )
- else:
- self.quota = value
- if not self.quota and self.domain.quota and not override_rules:
- raise BadRequest(_("A quota is required"))
-
- def get_quota(self):
- """Get quota limit.
-
- :rtype: int
- """
- return int(self.quota_value.bytes / 1048576)
-
- def get_quota_in_percent(self):
- """Get current quota usage.
-
- :rtype: int
- """
- if not self.quota:
- return 0
- return int(
- self.quota_value.bytes / float(self.quota * 1048576) * 100
- )
-
- def post_create(self, creator):
- from modoboa.lib.permissions import grant_access_to_object
- super(Mailbox, self).post_create(creator)
- if creator.is_superuser and not self.user.has_perm("admin.add_domain"):
- # A super user is creating a new mailbox. Give
- # access to that mailbox (and the associated
- # account) to the appropriate domain admins,
- # except if the new account has a more important
- # role (SuperAdmin, Reseller)
- for admin in self.domain.admins:
- grant_access_to_object(admin, self)
- grant_access_to_object(admin, self.user)
-
- def save(self, *args, **kwargs):
- """Custom save.
-
- We just make sure a quota record is defined for this mailbox.
- """
- if self.quota_value is None:
- self.quota_value, created = Quota.objects.get_or_create(
- username=self.full_address)
- super(Mailbox, self).save(*args, **kwargs)
-
- def delete(self, keepdir=False):
- """Custom delete method
-
- We try to delete the associated quota in the same time (it may
- has already been removed if we're deleting a domain).
-
- :param bool keepdir: delete the mailbox home dir on the
- filesystem or not
-
- """
- try:
- q = Quota.objects.get(username=self.full_address)
- except Quota.DoesNotExist:
- pass
- else:
- q.delete()
- if not keepdir:
- self.delete_dir()
- super(Mailbox, self).delete()
-
-reversion.register(Mailbox)
-
-
-@receiver(pre_delete, sender=Mailbox)
-def mailbox_deleted_handler(sender, **kwargs):
- """``Mailbox`` pre_delete signal receiver
-
- In order to properly handle deletions (ie. we don't want to leave
- orphan records into the db), we define this custom receiver.
-
- It manually removes the mailbox from the aliases it is linked to
- and then remove all empty aliases.
- """
- from modoboa.lib.permissions import ungrant_access_to_object
-
- mb = kwargs['instance']
- events.raiseEvent("MailboxDeleted", mb)
- ungrant_access_to_object(mb)
- for alias in mb.alias_set.all():
- alias.mboxes.remove(mb)
- if alias.mboxes.count() == 0:
- alias.delete()
-
-
-class MailboxOperation(models.Model):
- mailbox = models.ForeignKey(Mailbox, blank=True, null=True)
- type = models.CharField(
- max_length=20, choices=(('rename', 'rename'), ('delete', 'delete'))
- )
- argument = models.TextField()
-
- class Meta:
- app_label = 'admin'
-
- def __str__(self):
- if self.type == 'rename':
- return 'Rename %s -> %s' % (self.argument, self.mailbox.mail_home)
- return 'Delete %s' % self.argument
diff --git a/modoboa/extensions/admin/modo_extension.py b/modoboa/extensions/admin/modo_extension.py
deleted file mode 100644
index 15d64de5b..000000000
--- a/modoboa/extensions/admin/modo_extension.py
+++ /dev/null
@@ -1,285 +0,0 @@
-"""Registration with Modoboa takes place here."""
-
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.extensions.admin.models import (
- Domain, DomainAlias, Mailbox, Alias
-)
-from modoboa.lib import parameters, events
-from modoboa.lib.email_utils import split_mailbox
-from modoboa.lib.exceptions import PermDeniedException, BadRequest, Conflict
-
-
-ADMIN_EVENTS = [
- "DomainCreated",
- "DomainModified",
- "DomainDeleted",
- "DomainOwnershipRemoved",
- "ExtraDomainEntries",
- "ExtraDomainMenuEntries",
- "ExtraDomainFilters",
- "GetDomainActions",
- "GetDomainModifyLink",
- "CheckDomainName",
-
- "DomainAliasCreated",
- "DomainAliasDeleted",
-
- "MailboxCreated",
- "MailboxDeleted",
- "MailboxModified",
-
- "MailboxAliasCreated",
- "MailboxAliasDeleted",
-
- "ExtraDomainForm",
- "FillDomainInstances",
-
- "ExtraAccountForm",
- "CheckExtraAccountForm",
- "FillAccountInstances",
-
- "ExtraDomainImportHelp",
- "ImportObject"
-]
-
-PERMISSIONS = {
- "DomainAdmins": [
- ["admin", "domain", "view_domain"],
- ["admin", "mailbox", "add_mailbox"],
- ["admin", "mailbox", "change_mailbox"],
- ["admin", "mailbox", "delete_mailbox"],
- ["admin", "alias", "add_alias"],
- ["admin", "alias", "change_alias"],
- ["admin", "alias", "delete_alias"],
- ["admin", "mailbox", "view_mailboxes"],
- ["admin", "alias", "view_aliases"],
- ["admin", "domainalias", "view_domaliases"],
- ["admin", "domainalias", "add_domainalias"],
- ["admin", "domainalias", "change_domainalias"],
- ["admin", "domainalias", "delete_domainalias"]
- ]
-}
-
-
-class AdminConsole(ModoExtension):
- name = "admin"
- label = ugettext_lazy("Administration console")
- version = "1.0"
- description = ugettext_lazy(
- "Web based console to manage domains, accounts and aliases"
- )
- always_active = True
-
- def load(self):
- from modoboa.extensions.admin.app_settings import AdminParametersForm
- parameters.register(
- AdminParametersForm, ugettext_lazy("Administration"))
- events.declare(ADMIN_EVENTS)
-
-exts_pool.register_extension(AdminConsole)
-
-
-@events.observe("GetExtraRolePermissions")
-def extra_permissions(rolename):
- """Return extra permissions for :kw:`rolename`."""
- return PERMISSIONS.get(rolename, [])
-
-
-@events.observe("ExtraUprefsRoutes")
-def extra_routes():
- from django.conf.urls import url
- return [
- url(r'^user/forward/',
- 'modoboa.extensions.admin.views.user.forward',
- name="user_forward"),
- ]
-
-
-@events.observe("AdminMenuDisplay")
-def admin_menu(target, user):
- if target != "top_menu":
- return []
- entries = []
- if user.has_perm("admin.view_domains"):
- entries += [
- {"name": "domains",
- "url": reverse("admin:domain_list"),
- "label": _("Domains")}
- ]
- if user.has_perm("core.add_user") or user.has_perm("admin.add_alias"):
- entries += [
- {"name": "identities",
- "url": reverse("admin:identity_list"),
- "label": _("Identities")},
- ]
- return entries
-
-
-@events.observe("UserMenuDisplay")
-def user_menu(target, user):
- if target != "uprefs_menu":
- return []
- if not user.mailbox_set.count():
- return []
- return [
- {"name": "forward",
- "class": "ajaxnav",
- "url": "forward/",
- "label": ugettext_lazy("Forward")}
- ]
-
-
-@events.observe("RoleChanged")
-def grant_access_to_all_objects(user, role):
- from django.contrib.contenttypes.models import ContentType
- from modoboa.lib.permissions import grant_access_to_objects
- from modoboa.core.models import User
-
- if role != "SuperAdmins":
- return
- grant_access_to_objects(
- user, User.objects.all(),
- ContentType.objects.get_for_model(User)
- )
- grant_access_to_objects(
- user, Domain.objects.all(),
- ContentType.objects.get_for_model(Domain)
- )
- grant_access_to_objects(
- user, DomainAlias.objects.all(),
- ContentType.objects.get_for_model(DomainAlias)
- )
- grant_access_to_objects(
- user, Mailbox.objects.all(),
- ContentType.objects.get_for_model(Mailbox)
- )
- grant_access_to_objects(
- user, Alias.objects.all(),
- ContentType.objects.get_for_model(Alias)
- )
-
-
-@events.observe("AccountExported")
-def export_admin_domains(admin):
- result = [admin.mailbox_set.all()[0].quota] \
- if admin.mailbox_set.count() else ['']
- if admin.group != "DomainAdmins":
- return result
- return result + [dom.name for dom in Domain.objects.get_for_admin(admin)]
-
-
-@events.observe("AccountImported")
-def import_account_mailbox(user, account, row):
- """Handle extra fields when an account is imported.
-
- Expected fields:
-
- email address; quota; [domain; ...]
-
- :param User user: user importing the account
- :param User account: account being imported
- :param list rom: list of fields (strings)
- """
- account.email = row[0].strip()
- if account.email:
- account.save()
- mailbox, domname = split_mailbox(account.email)
- try:
- domain = Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- raise BadRequest(
- _("Account import failed (%s): domain does not exist"
- % account.username)
- )
- if not user.can_access(domain):
- raise PermDeniedException
- try:
- mb = Mailbox.objects.get(address=mailbox, domain=domain)
- except Mailbox.DoesNotExist:
- pass
- else:
- raise Conflict(_("Mailbox %s already exists" % account.email))
- if len(row) == 1:
- quota = None
- else:
- try:
- quota = int(row[1].strip())
- except ValueError:
- raise BadRequest(
- _("Account import failed (%s): wrong quota value"
- % account.username)
- )
- use_domain_quota = True if not quota else False
- mb = Mailbox(address=mailbox, domain=domain,
- user=account, use_domain_quota=use_domain_quota)
- mb.set_quota(quota, override_rules=user.has_perm("admin.change_domain"))
- mb.save(creator=user)
- if account.group == "DomainAdmins":
- for domname in row[2:]:
- try:
- dom = Domain.objects.get(name=domname.strip())
- except Domain.DoesNotExist:
- continue
- dom.add_admin(account)
-
-
-@events.observe("AccountAutoCreated")
-def account_auto_created(user):
- from modoboa.core.models import User
- from modoboa.extensions.admin.lib import check_if_domain_exists
- from modoboa.lib.permissions import grant_access_to_object
-
- if parameters.get_admin("AUTO_CREATE_DOMAIN_AND_MAILBOX") == "no":
- return
- localpart, domname = split_mailbox(user.username)
- if user.group != 'SimpleUsers' and domname is None:
- return
- sadmins = User.objects.filter(is_superuser=True)
- try:
- domain = Domain.objects.get(name=domname)
- except Domain.DoesNotExist:
- label = check_if_domain_exists(
- domname, [(DomainAlias, _('domain alias'))])
- if label is not None:
- return
- domain = Domain(name=domname, enabled=True, quota=0)
- domain.save(creator=sadmins[0])
- for su in sadmins[1:]:
- grant_access_to_object(su, domain)
- try:
- mb = Mailbox.objects.get(domain=domain, address=localpart)
- except Mailbox.DoesNotExist:
- mb = Mailbox(
- address=localpart, domain=domain, user=user, use_domain_quota=True
- )
- mb.set_quota(override_rules=True)
- mb.save(creator=sadmins[0])
- for su in sadmins[1:]:
- grant_access_to_object(su, mb)
-
-
-@events.observe("UserLogin")
-def user_logged_in(request, username, password):
- from modoboa.lib.cryptutils import encrypt
-
- if request.user.mailbox_set.count():
- request.session["password"] = encrypt(password)
-
-
-@events.observe("AccountDeleted")
-def account_deleted(account, byuser, **kwargs):
- """'AccountDeleted' listener.
-
- When an account is deleted, we also need to remove its mailbox (if
- any).
- """
- if not account.mailbox_set.count():
- return
- mb = account.mailbox_set.all()[0]
- if not byuser.can_access(mb):
- raise PermDeniedException
- keep_mb_dir = kwargs.get("keep_mb_dir", True)
- mb.delete(keepdir=keep_mb_dir)
diff --git a/modoboa/extensions/admin/static/admin/css/admin.css b/modoboa/extensions/admin/static/admin/css/admin.css
deleted file mode 100644
index 2768bf843..000000000
--- a/modoboa/extensions/admin/static/admin/css/admin.css
+++ /dev/null
@@ -1,33 +0,0 @@
-#searchform {
- margin-bottom: 10px;
-}
-
-span.title {
- margin-left: 40px;
- margin-bottom: 10px;
- float: left;
- font-weight: bold;
- width: 180px;
-}
-
-table th#actions {
- text-align: right;
-}
-
-table td[name="actions"] {
- text-align: right;
-}
-
-table .progress {
- margin-bottom: 0 !important;
-}
-
-table tbody tr:hover {
- background-color: #F9F9F9;
-}
-
-.search {
- width: 85%;
- -webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;
- padding-left: 14px;
-}
diff --git a/modoboa/extensions/admin/static/admin/css/settings.css b/modoboa/extensions/admin/static/admin/css/settings.css
deleted file mode 100644
index 24fc269b9..000000000
--- a/modoboa/extensions/admin/static/admin/css/settings.css
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#settings_content .form-horizontal .control-label {
- margin-left: 20px;
- text-align: left;
-}
-
-#settings_content > .form-horizontal .controls {
- margin-left: 240px;
-}
\ No newline at end of file
diff --git a/modoboa/extensions/admin/static/admin/js/admin.js b/modoboa/extensions/admin/static/admin/js/admin.js
deleted file mode 100644
index 85eb24af9..000000000
--- a/modoboa/extensions/admin/static/admin/js/admin.js
+++ /dev/null
@@ -1,556 +0,0 @@
-/**
- * Creates an instance of Admin.
- *
- * @constructor
- * @param {Object} options - instance options
- * @classdesc This class contains utility methods used by the admin
- * application.
- */
-var Admin = function(options) {
- Listing.call(this, options);
-};
-
-Admin.prototype = {
- defaults: {
- deflocation: "list/",
- squery: null
- },
-
- initialize: function(options) {
- this.options = $.extend({}, this.defaults, options);
- this.options.defcallback = $.proxy(this.list_cb, this);
- Listing.prototype.initialize.call(this, this.options);
- this.listen();
- },
-
- /**
- * Callback used when the initial content of the listing is
- * received.
- *
- * @this Admin
- * @param {Object} data - response of the ajax call (JSON)
- */
- list_cb: function(data) {
- if (data.rows) {
- $("#objects_table tbody").html(data.rows);
- } else {
- $("#objects_table tbody").html("");
- }
- this.update_listing(data);
- if (data.length === 0) {
- this.get_load_page_args();
- this.end_of_list_reached();
- }
- },
-
- /**
- * Children must override this method.
- */
- listen: function() {
- },
-
- /**
- * Load a new page using an AJAX request.
- *
- * @this Admin
- * @param {Object} e - event object
- */
- page_loader: function(e) {
- var $link = get_target(e);
- e.preventDefault();
- if ($link.hasClass("navigation")) {
- $(".sidebar li.active").removeClass("active");
- $link.parent().addClass("active");
- }
- this.navobj.baseurl($link.attr("href")).update();
- },
-
- importform_cb: function() {
- $(".submit").one('click', function(e) {
- e.preventDefault();
- if ($("#id_sourcefile").val() === "") {
- return;
- }
- $("#import_status").css("display", "block");
- $("#import_result").html("").removeClass("alert alert-danger");
- $("#importform").submit();
- });
- },
-
- importdone: function(status, msg) {
- $("#import_status").css("display", "none");
- if (status == "ok") {
- $("#modalbox").modal('hide');
- this.reload_listing(msg);
- } else {
- $("#import_result").addClass("alert alert-danger");
- $("#import_result").html(msg);
- this.importform_cb();
- }
- },
-
- exportform_cb: function() {
- $(".submit").one('click', function(e) {
- e.preventDefault();
- $("#exportform").submit();
- $("#modalbox").modal('hide');
- });
- },
-
- reload_listing: function(data) {
- this.navobj.update(true);
- if (data) {
- $("body").notify("success", data, 2000);
- }
- }
-};
-
-Admin.prototype = $.extend({}, Listing.prototype, Admin.prototype);
-
-/**
- * Creates an instance of Domains.
- *
- * @constructor
- * @param {Object} options - instance options
- * @classdesc This class extends the Admin one by adding methods
- * specific to domains management.
- */
-var Domains = function(options) {
- Admin.call(this, options);
-};
-
-Domains.prototype = {
- initialize: function(options) {
- Admin.prototype.initialize.call(this, options);
- this.options.navigation_params.push("domfilter", "srvfilter");
- this.options.eor_message = gettext("No more domain to show");
- this.register_tag_handler("dom");
- },
-
- /**
- * Custom callbacks declaration.
- */
- listen: function() {
- Admin.prototype.listen.call(this);
- $(document).on("click", "a.ajaxnav", $.proxy(this.page_loader, this));
- },
-
- /**
- * Initialize the domain links embedded within a page.
- *
- * @param {Object} data - options
- */
- init_domain_links: function(data) {
- var deloptions = (data.handle_mailboxes) ?
- {keepdir: gettext("Do not delete domain directory")} : {};
- var warnmsg = (data.auto_account_removal && data.auto_account_removal == "yes")
- ? gettext("This operation will remove ALL data associated to this domain.")
- : gettext("This operation will remove all data associated to this domain, excepting accounts.");
-
- $("a[name=deldomain]").confirm({
- question: function() { return this.$element.attr('title'); },
- method: "POST",
- warning: warnmsg,
- checkboxes: deloptions,
- success_cb: $.proxy(this.reload_listing, this)
- });
- $(document).trigger('domain_listing_refresh');
- },
-
- /**
- * Navigation callback: default.
- *
- * @param {Object} data - response of the ajax call (JSON)
- */
- list_cb: function(data) {
- Admin.prototype.list_cb.call(this, data);
- this.init_domain_links(data);
- },
-
- /**
- * A new page has been received, inject it.
- *
- * @param {Object} data - page content
- * @param {string} direction -
- */
- add_new_page: function(data, direction) {
- Admin.prototype.add_new_page.call(this, data, direction);
- this.init_domain_links(data);
- },
-
- change_inputs_state: function(value) {
- $("#id_dom_admin_username").attr("disabled", value);
- $("input[name=create_aliases]").attr("disabled", value);
- },
-
- create_dom_admin_changed: function(e) {
- var $target = $(e.target);
- this.change_inputs_state(($target.val() == "yes") ? false : true);
- },
-
- /**
- * Initialize the main form contained in the domain edition modal.
- *
- * @this Domains
- */
- generalform_init: function() {
- $('input:text:visible:first').focus();
- $("#original_aliases").dynamic_input({
- input_added: function($row) {
- $row.find("label").html("");
- },
- input_removed: function($input) {
- $input.parents(".form-group").remove();
- return true;
- }
- });
- },
-
- optionsform_init: function() {
- $("input[name=create_dom_admin]").click($.proxy(this.create_dom_admin_changed, this));
- this.change_inputs_state(
- $("input[name=create_dom_admin]:checked").val() == "yes" ? false : true
- );
- this.optionsform_prefill();
- },
-
- optionsform_prefill: function() {
- var $span = $("#id_dom_admin_username").next("span");
- $span.html("@" + $("#id_name").val());
- },
-
- domadminsform_init: function() {
- $("a[name=removeperm]").click(function(e) {
- var $tr = $(this).parents('tr');
- simple_ajax_request.apply(this, [e, {
- ok_cb: function(resp) {
- $tr.remove();
- if (!$("#domadmins").find("tr").length) {
- $("#admins").html(''
- + gettext("No domain administrator defined") + "
");
- }
- }
- }]);
- });
- },
-
- newdomain_cb: function() {
- this.generalform_init();
- this.optionsform_init();
- $("#wizard").cwizard({
- formid: "domform",
- transition_callbacks: {
- 1: this.optionsform_prefill
- },
- error_callbacks: {
- 2: $.proxy(this.optionsform_init, this)
- },
- success_callback: $.proxy(this.reload_listing, this)
- });
- },
-
- domainform_cb: function() {
- this.generalform_init();
- this.domadminsform_init();
- $(".submit").one('click', $.proxy(function(e) {
- simple_ajax_form_post(e, {
- formid: "domform",
- error_cb: $.proxy(this.domainform_cb, this),
- reload_on_success: false,
- success_cb: $.proxy(this.reload_listing, this)
- });
- }, this));
- $(document).trigger('domform_init');
- }
-};
-
-Domains.prototype = $.extend({}, Admin.prototype, Domains.prototype);
-
-/**
- * Creates an instance of Identities.
- *
- * @constructor
- * @param {Object} options - instance options
- * @classdesc This class extends the Admin one by adding methods
- * specific to identities management.
- */
-var Identities = function(options) {
- Admin.call(this, options);
-};
-
-Identities.prototype = {
- initialize: function(options) {
- Admin.prototype.initialize.call(this, options);
- this.options.navigation_params.push("idtfilter", "grpfilter");
- this.options.eor_message = gettext("No more identity to show");
- this.domain_list = [];
- this.register_tag_handler("idt");
- this.register_tag_handler("grp", this.grp_tag_handler);
- },
-
- listen: function() {
- Admin.prototype.listen.call(this);
- $(document).on("click", "a.ajaxnav", $.proxy(this.page_loader, this));
- $(document).on("click", "a.ajaxcall", $.proxy(this.send_call, this));
- },
-
- /**
- * Send an ajax call.
- */
- send_call: function(evt) {
- var $link = get_target(evt, "a");
- var $this = this;
- var method = $link.attr("data-call_method");
-
- if (method === undefined) {
- method = "GET";
- }
- evt.preventDefault();
- $.ajax({
- url: $link.attr("href"),
- type: method,
- dataType: "json"
- }).done(function(data) {
- $this.reload_listing(data.respmsg);
- });
- },
-
- /**
- * Initialize the links embedded within a page.
- *
- * @param {Object} data - options
- */
- init_identity_links: function(data) {
- var deloptions = {};
-
- if (data.handle_mailboxes == "yes") {
- deloptions = {keepdir: gettext("Do not delete mailbox directory")};
- }
-
- $("a[name=delaccount]").confirm({
- question: function() { return this.$element.attr('title'); },
- method: "POST",
- checkboxes: deloptions,
- success_cb: $.proxy(this.reload_listing, this)
- });
- $("a[name=delalias]").confirm({
- question: function() { return this.$element.attr('title'); },
- method: "DELETE",
- success_cb: $.proxy(this.reload_listing, this)
- });
- },
-
- /**
- * Add a type to let the server know what kind of object we expect.
- *
- * @this Listing
- */
- get_load_page_args: function() {
- var args = Admin.prototype.get_load_page_args.call(this);
-
- if (this.navobj.getbaseurl() == "list") {
- args.objtype = "identity";
- this.options.eor_message = gettext("No more identity to show");
- } else {
- args.objtype = "quota";
- this.options.eor_message = gettext("No more quota to show");
- }
- return args;
- },
-
- /**
- * A new page has been received, inject it.
- *
- * @param {Object} data - page content
- * @param {string} direction -
- */
- add_new_page: function(data, direction) {
- Admin.prototype.add_new_page.call(this, data, direction);
- this.init_identity_links(data);
- },
-
- /**
- * Navigation callback: default.
- *
- * @param {Object} data - response of the ajax call (JSON)
- */
- list_cb: function(data) {
- if ($(".sidebar li.active").length === 0) {
- var menu = this.navobj.getbaseurl();
- if (menu == "list") {
- menu = "identities";
- }
- $("a[name={0}]".format(menu)).parent().addClass("active");
- }
- $("#objects_table thead tr").html(data.headers);
- Admin.prototype.list_cb.call(this, data);
- this.init_identity_links(data);
- },
-
- grp_tag_handler: function(tag, $link) {
- if (this.navobj.getparam(tag + "filter") === undefined &&
- $link.hasClass(tag)) {
- var text = $link.attr("name");
- this.navobj
- .setparam("idtfilter", "account")
- .setparam(tag + "filter", text)
- .update();
- if ($("a[name=idt]").length === 0) {
- $("#taglist").append(this.make_tag("account", "idt"));
- }
- $("#taglist").append(this.make_tag(text, tag));
- return true;
- }
- return false;
- },
-
- /**
- * Retrieve a list of domain from the server.
- *
- * @this Identities
- * @return {Array} a list of domain names
- */
- get_domain_list: function() {
- if (!this.domain_list.length) {
- $.ajax({
- url: this.options.domain_list_url,
- dataType: "json",
- async: false
- }).done($.proxy(function(data) {
- this.domain_list = data;
- }, this));
- }
- return this.domain_list;
- },
-
- simpleuser_mode: function() {
- $("#id_username").autocompleter({
- from_character: "@",
- choices: $.proxy(this.get_domain_list, this)
- });
- $("#id_email").addClass("disabled")
- .attr("readonly", "")
- .autocompleter("unbind");
- },
-
- normal_mode: function() {
- $("#id_email").removeClass("disabled")
- .attr("readonly", null)
- .autocompleter("listen");
- },
-
- generalform_init: function(notrigger) {
- $("#id_role").change($.proxy(function(e) {
- var $this = $(e.target);
- var value = $this.val();
-
- if (value == "SimpleUsers" || value === "") {
- this.simpleuser_mode();
- } else {
- this.normal_mode();
- }
- }, this));
- if (notrigger !== undefined && notrigger) {
- return;
- }
- $("#id_role").trigger("change");
- },
-
- mailform_init: function() {
- $("#id_aliases").autocompleter({
- from_character: "@",
- choices: $.proxy(this.get_domain_list, this)
- });
- $("#original_aliases").dynamic_input({
- input_added: function($row) {
- $row.find("label").html("");
- },
- input_removed: function($input) {
- $input.parents(".form-group").remove();
- return true;
- }
- });
- $("#id_email").autocompleter({
- from_character: "@",
- choices: $.proxy(this.get_domain_list, this)
- });
- if ($("#id_role").length) {
- $("#id_role").trigger("change");
- } else {
- this.simpleuser_mode();
- }
- $("#id_domains").autocompleter({
- choices: $.proxy(this.get_domain_list, this)
- });
- $("#original_domains").dynamic_input({
- input_added: function($row) {
- $row.find("label").html("");
- },
- input_removed: function($input) {
- $input.parents(".form-group").remove();
- return true;
- }
- });
- activate_widget.call($("#id_quota_act"));
- },
-
- accountform_init: function() {
- this.generalform_init(true);
- this.mailform_init();
- },
-
- mailform_prefill: function() {
- var $role = $("#id_role");
- if (!$role.length || $role.val() === "" || $role.val() == "SimpleUsers") {
- $("#id_email").val($("#id_username").val());
- }
- },
-
- newaccount_cb: function() {
- this.accountform_init();
- $("#wizard").cwizard({
- formid: "newaccount_form",
- transition_callbacks: {
- 1: this.mailform_prefill
- },
- success_callback: $.proxy(this.reload_listing, this)
- });
- },
-
- editaccount_cb: function() {
- this.accountform_init();
- $('.submit').on('click', $.proxy(function(e) {
- simple_ajax_form_post(e, {
- formid: "accountform",
- reload_on_success: false,
- success_cb: $.proxy(this.reload_listing, this)
- });
- }, this));
- },
-
- aliasform_cb: function() {
- $("#id_email").autocompleter({
- from_character: "@",
- choices: $.proxy(this.get_domain_list, this)
- });
- $("#original_recipients").dynamic_input({
- input_added: function($row) {
- $row.find("label").html("");
- },
- input_removed: function($input) {
- $input.parents(".form-group").remove();
- return true;
- }
- });
- $(".submit").on('click', $.proxy(function(e) {
- simple_ajax_form_post(e, {
- formid: "aliasform",
- reload_on_success: false,
- success_cb: $.proxy(this.reload_listing, this)
- });
- }, this));
- }
-
-};
-
-Identities.prototype = $.extend({}, Admin.prototype, Identities.prototype);
diff --git a/modoboa/extensions/admin/tables.py b/modoboa/extensions/admin/tables.py
deleted file mode 100644
index d8f4f1c8d..000000000
--- a/modoboa/extensions/admin/tables.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# coding: utf-8
-from django.utils.translation import ugettext_lazy
-from modoboa.lib import tables
-
-
-class ExtensionsTable(tables.Table):
- idkey = "id"
- selection = tables.SelectionColumn("selection", width="4%", header=False)
- label = tables.Column("label", label=ugettext_lazy("Name"), width="15%")
- version = tables.Column(
- "version", label=ugettext_lazy("Version"), width="6%"
- )
- descr = tables.Column("description", label=ugettext_lazy("Description"))
-
- cols_order = ["selection", "label", "version", "descr"]
diff --git a/modoboa/extensions/admin/templates/admin/account_general_form.html b/modoboa/extensions/admin/templates/admin/account_general_form.html
deleted file mode 100644
index 3df108317..000000000
--- a/modoboa/extensions/admin/templates/admin/account_general_form.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% load form_tags %}
-{% render_field form.role %}
-{% render_field form.username %}
-{% render_field form.first_name %}
-{% render_field form.last_name %}
-{% render_field form.password1 %}
-{% render_field form.password2 %}
-{% if form.domain_is_disabled %}
-{% include "common/generic_field.html" with field=form.is_active label_width="col-sm-4" inline_message=_("Domain is disabled") %}
-{% else %}
-{% render_field form.is_active %}
-{% endif %}
diff --git a/modoboa/extensions/admin/templates/admin/aliasform.html b/modoboa/extensions/admin/templates/admin/aliasform.html
deleted file mode 100644
index 5eef9092c..000000000
--- a/modoboa/extensions/admin/templates/admin/aliasform.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% extends "common/generic_modal_form.html" %}{% load form_tags %}
-{% block formbody %}
-{% render_field form.email %}
-{% render_fields_group form "recipients" %}
-{% if not form.instance.pk or form.instance.domain.enabled %}
-{% render_field form.enabled %}
-{% else %}
-{% include "common/generic_field.html" with field=form.enabled label_width="col-sm-4" inline_message=_("Domain is disabled") extra_classes="info" %}
-{% endif %}
-{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/domain_general_form.html b/modoboa/extensions/admin/templates/admin/domain_general_form.html
deleted file mode 100644
index 7a79f0b51..000000000
--- a/modoboa/extensions/admin/templates/admin/domain_general_form.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% load i18n form_tags %}
-{% render_field form.name %}
-{% render_field form.quota appended_text=_("MB") %}
-{% render_fields_group form "aliases" %}
-{% render_field form.enabled %}
diff --git a/modoboa/extensions/admin/templates/admin/domain_options_form.html b/modoboa/extensions/admin/templates/admin/domain_options_form.html
deleted file mode 100644
index 0993c11fa..000000000
--- a/modoboa/extensions/admin/templates/admin/domain_options_form.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% load i18n form_tags %}
-{% if form.fields %}
-{% render_field form.create_dom_admin %}
-{% render_field form.dom_admin_username appended_text="@" %}
-{% render_field form.create_aliases %}
-{% else %}
-{% trans "You can't create a new domain administrator" %}
-{% endif %}
diff --git a/modoboa/extensions/admin/templates/admin/domain_statistics.html b/modoboa/extensions/admin/templates/admin/domain_statistics.html
deleted file mode 100644
index 2be458dab..000000000
--- a/modoboa/extensions/admin/templates/admin/domain_statistics.html
+++ /dev/null
@@ -1,63 +0,0 @@
-{% extends "admin/header.html" %}
-
-{% load i18n %}
-{% load admin_tags %}
-
-{% block leftcol %}
-
-
-{% get_extra_admin_content user "leftcol" selection %}
-{% endblock %}
-
-{% block apparea %}
-{% trans "Statistics" %} {% trans "Domains and identities" %}
-
-
-
- {% if user.group == "SuperAdmins" %}
-
-
-
{% trans "Global counters" %}
-
-
-
- {% trans "Type" %}
- {% trans "Quantity" %}
-
-
- {% trans "Domains" %} {{ domains_counter }}
-
-
- {% trans "Domain aliases" %} {{ domain_aliases_counter }}
-
-
- {% trans "Identities" %} {{ identities_counter }}
-
-
-
-
- {% endif %}
-
-
-
-
{% trans "Per-domain counters" %}
-
-
-
- {% trans "Domain" %}
- {% trans "Identities" %}
-
- {% for domain in domains %}
-
- {{ domain.name }} {{ domain.identities_count }}
-
- {% endfor %}
-
-
-
-
-
-
-{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/domains.html b/modoboa/extensions/admin/templates/admin/domains.html
deleted file mode 100644
index ec4025f0c..000000000
--- a/modoboa/extensions/admin/templates/admin/domains.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% extends "admin/listing.html" %}{% load i18n admin_tags lib_tags %}
-
-{% block pagetitle %}{% trans "Domains" %}{% endblock %}
-
-{% block extra_css %}
-{{ block.super }}
-{% extra_static_content "domains" "css" user %}
-{% endblock %}
-
-{% block extra_js %}
-{{ block.super }}
-
-{% extra_static_content "domains" "js" user %}
-{% endblock %}
-
-{% block actions %}{% domains_menu "domains" user %}{% endblock %}
-
-{% block table_header %}
-{% trans "Name" %}
-{% trans "Alias(es)" %}
-{% trans "Tags" %}
-{% trans "Actions" %}
-{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/domains_table.html b/modoboa/extensions/admin/templates/admin/domains_table.html
deleted file mode 100644
index c79777a8b..000000000
--- a/modoboa/extensions/admin/templates/admin/domains_table.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% load i18n admin_tags lib_tags %}
-{% for domain in domains %}
-
- {% domain_modify_link domain %}{% if not domain.enabled %} ({% trans "disabled" %}){% endif %}
- {% domain_aliases domain %}
- {% render_tags domain.tags %}
- {% domain_actions user domain %}
-
-{% endfor %}
diff --git a/modoboa/extensions/admin/templates/admin/editdomainform.html b/modoboa/extensions/admin/templates/admin/editdomainform.html
deleted file mode 100644
index 09d19065f..000000000
--- a/modoboa/extensions/admin/templates/admin/editdomainform.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "common/tabforms.html" %}{% load i18n lib_tags admin_tags %}
-{% block extratabs %}
-
- {% trans "Administrators" %}
-
-
- {% trans "Miscellaneous" %}
-
-{% endblock %}
-{% block extratabs_content %}
-{% if domadmins %}
-
- {% trans "Username" %} {% trans "Name" %}
- {% for da in domadmins %}
- {{ da.username }}
- {{ da.fullname }}
- {% if perms.admin.change_domain %}{% domadmin_actions da.id domain.id %}{% endif %}
- {% endfor %}
-
{% else %}
{% trans "No domain administrator defined" %}
{% endif %}
-
-
-
{% trans "Creation date" %} {{ domain.creation }}
-
{% trans "Last modification date" %} {{ domain.last_modification }}
-
{% trans "Domain aliases" %} {{ domain.domainalias_count }}
-
{% trans "Mailboxes" %} {{ domain.mailbox_count }}
-
{% trans "Mailbox aliases" %} {{ domain.mbalias_count }}
-
-{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/forward.html b/modoboa/extensions/admin/templates/admin/forward.html
deleted file mode 100644
index 3146beea6..000000000
--- a/modoboa/extensions/admin/templates/admin/forward.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% load i18n form_tags %}{% load url from future %}
-{% trans "Forward" %} {% trans "Automatically forward emails to another address" %}
-
-
diff --git a/modoboa/extensions/admin/templates/admin/header.html b/modoboa/extensions/admin/templates/admin/header.html
deleted file mode 100644
index 1dacea7a8..000000000
--- a/modoboa/extensions/admin/templates/admin/header.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% extends "twocols.html" %}
-{% load static %}
-
-{% block extra_css %}
-
-{% endblock %}
-
-{% block extra_js %}
-
-
-
-{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/identities.html b/modoboa/extensions/admin/templates/admin/identities.html
deleted file mode 100644
index dde5b0e5f..000000000
--- a/modoboa/extensions/admin/templates/admin/identities.html
+++ /dev/null
@@ -1,26 +0,0 @@
-{% extends "admin/listing.html" %}
-{% load admin_tags lib_tags i18n %}{% load url from future %}
-{% load static %}
-
-{% block pagetitle %}{% trans "Identities" %}{% endblock %}
-
-{% block extra_css %}
-{{ block.super }}
-{% extra_static_content "identities" "css" user %}
-{% endblock %}
-
-{% block extra_js %}
-{{ block.super }}
-
-
-{% extra_static_content "identities" "js" user %}
-{% endblock %}
-
-{% block actions %}{% identities_menu user "identities" %}{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/identities_table.html b/modoboa/extensions/admin/templates/admin/identities_table.html
deleted file mode 100644
index 15fad1e00..000000000
--- a/modoboa/extensions/admin/templates/admin/identities_table.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% load i18n admin_tags lib_tags %}
-{% for ident in identities %}
- {% check_identity_status ident as identity_is_enabled %}
-
- {% identity_modify_link ident %}{% if not identity_is_enabled %} (disabled){% endif %}
- {{ ident.name_or_rcpt }}
- {% render_tags ident.tags %}
- {% identity_actions user ident %}
-
-{% endfor %}
diff --git a/modoboa/extensions/admin/templates/admin/identity_headers.html b/modoboa/extensions/admin/templates/admin/identity_headers.html
deleted file mode 100644
index 53c18e745..000000000
--- a/modoboa/extensions/admin/templates/admin/identity_headers.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% load i18n %}
-{% trans "Name" %}
-{% trans "Fullname/Recipient" %}
-{% trans "Tags" %}
-{% trans "Actions" %}
diff --git a/modoboa/extensions/admin/templates/admin/import_done.html b/modoboa/extensions/admin/templates/admin/import_done.html
deleted file mode 100644
index 55a3191b0..000000000
--- a/modoboa/extensions/admin/templates/admin/import_done.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/modoboa/extensions/admin/templates/admin/importform.html b/modoboa/extensions/admin/templates/admin/importform.html
deleted file mode 100644
index 8e15acf69..000000000
--- a/modoboa/extensions/admin/templates/admin/importform.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% extends "common/generic_modal_form.html" %}
-{% load form_tags i18n %}
-{% load static %}
-{% block formbody %}
-
-
{% trans "Help" %}
- {{ helptext|safe }}
-
-{% render_form form %}
-
-
-
{% trans "Importing..." %}
-
-
-{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/listing.html b/modoboa/extensions/admin/templates/admin/listing.html
deleted file mode 100644
index a5c5c7dbb..000000000
--- a/modoboa/extensions/admin/templates/admin/listing.html
+++ /dev/null
@@ -1,47 +0,0 @@
-{% extends "admin/header.html" %}{% load i18n admin_tags %}
-{% load static %}
-
-{% block extra_css %}
-{{ block.super }}
-
-{% endblock %}
-
-{% block extra_js %}
-{{ block.super }}
-
-
-
-
-
-{% endblock %}
-
-{% block leftcol %}
-
-
-{% get_extra_admin_content user "leftcol" selection %}
-{% endblock %}
-
-{% block apparea %}
-
-
- {% include "admin/searchform.html" %}
-
-
-
-
-
-
-
-
- {% block table_header %}{% endblock %}
-
-
-
-
-
-
-{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/mailboxes_raw.html b/modoboa/extensions/admin/templates/admin/mailboxes_raw.html
deleted file mode 100644
index 9723f4a20..000000000
--- a/modoboa/extensions/admin/templates/admin/mailboxes_raw.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% load i18n %}
-{% if target == "permissions" %}
-{% trans "Choose a value" %}
-{% endif %}
-{% for mb in mailboxes %}
-{% if target == "permissions" %}
-{{ mb.name }}
-{% else %}
-{{ mb.full_address }}
-{% endif %}
-{% endfor %}
diff --git a/modoboa/extensions/admin/templates/admin/mailform.html b/modoboa/extensions/admin/templates/admin/mailform.html
deleted file mode 100644
index 4b7b6ec63..000000000
--- a/modoboa/extensions/admin/templates/admin/mailform.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% load form_tags %}
-{% render_field form.email %}
-{% include "common/generic_field.html" with field=form.quota help_display_mode="tooltip" label_width="col-sm-4" appended_text=_("MB") activator=True activator_value=form.quota_act.value deactivate_if_empty=False activator_label=_("Use domain default value") activator_size="col-sm-5" %}
-{% render_extra_fields form %}
-{% render_fields_group form "aliases" %}
diff --git a/modoboa/extensions/admin/templates/admin/newdomainform.html b/modoboa/extensions/admin/templates/admin/newdomainform.html
deleted file mode 100644
index 8b4d2ba29..000000000
--- a/modoboa/extensions/admin/templates/admin/newdomainform.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% extends "common/generic_modal_form.html" %}{% load form_tags %}{% block formbody %}
-{% render_field form.name %}
-{% render_field form.quota appended_text=_("MB") %}
-{% render_fields_group form "aliases" %}
-{% render_field form.enabled %}
-{% endblock %}
diff --git a/modoboa/extensions/admin/templates/admin/permsform.html b/modoboa/extensions/admin/templates/admin/permsform.html
deleted file mode 100644
index b1856a04e..000000000
--- a/modoboa/extensions/admin/templates/admin/permsform.html
+++ /dev/null
@@ -1,2 +0,0 @@
-{% load form_tags %}
-{% render_fields_group form "domains" %}
diff --git a/modoboa/extensions/admin/templates/admin/quota_headers.html b/modoboa/extensions/admin/templates/admin/quota_headers.html
deleted file mode 100644
index e496973e0..000000000
--- a/modoboa/extensions/admin/templates/admin/quota_headers.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% load i18n %}
-{% trans "Address" %}
-{% trans "Value" %}
-{% trans "Limit" %}
-{% trans "Usage (%)" %}
diff --git a/modoboa/extensions/admin/templates/admin/quotas.html b/modoboa/extensions/admin/templates/admin/quotas.html
deleted file mode 100644
index 266474b21..000000000
--- a/modoboa/extensions/admin/templates/admin/quotas.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% load lib_tags admin_tags %}
-
-{% for mbox in mboxes %}
-
- {% identity_modify_link mbox.user "mail" %}
- {{ mbox.get_quota }}M
- {{ mbox.quota }}M
-
-
-
-
-{% endfor %}
diff --git a/modoboa/extensions/admin/templates/admin/searchform.html b/modoboa/extensions/admin/templates/admin/searchform.html
deleted file mode 100644
index bac694e17..000000000
--- a/modoboa/extensions/admin/templates/admin/searchform.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% load i18n %}
-
diff --git a/modoboa/extensions/admin/templatetags/__init__.py b/modoboa/extensions/admin/templatetags/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/admin/templatetags/admin_tags.py b/modoboa/extensions/admin/templatetags/admin_tags.py
deleted file mode 100644
index d05b8ad9c..000000000
--- a/modoboa/extensions/admin/templatetags/admin_tags.py
+++ /dev/null
@@ -1,280 +0,0 @@
-"""
-Admin extension tags.
-"""
-
-from django import template
-from django.core.urlresolvers import reverse
-from django.template.loader import render_to_string
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.lib import events
-from modoboa.lib.templatetags.lib_tags import render_link
-from modoboa.lib.web_utils import render_actions
-
-register = template.Library()
-
-genders = {
- "Enabled": (ugettext_lazy("enabled_m"), ugettext_lazy("enabled_f"))
-}
-
-
-@register.simple_tag
-def domains_menu(selection, user):
- """Specific menu for domain related operations.
-
- Corresponds to the menu visible on the left column when you go to
- *Domains*.
-
- :param str selection: menu entry currently selected
- :param ``User`` user: connected user
- :rtype: str
- :return: rendered menu (as HTML)
- """
- domain_list_url = (
- "list/" if selection != "statistics" else reverse("admin:domain_list")
- )
- entries = [
- {"name": "domains",
- "label": _("List domains"),
- "img": "fa fa-user",
- "class": "ajaxnav navigation",
- "url": domain_list_url},
- {"name": "statistics",
- "label": _("Statistics"),
- "img": "fa fa-line-chart",
- "class": "navigation",
- "url": reverse("admin:domain_statistics")}
- ]
- if user.has_perm("admin.add_domain"):
- entries += [
- {"name": "newdomain",
- "label": _("Add domain"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "admin.newdomain_cb",
- "url": reverse("admin:domain_add")},
- ]
- entries += events.raiseQueryEvent("ExtraDomainMenuEntries", user)
- entries += [
- {"name": "import",
- "label": _("Import"),
- "img": "fa fa-folder-open",
- "url": reverse("admin:domain_import"),
- "modal": True,
- "modalcb": "admin.importform_cb"},
- {"name": "export",
- "label": _("Export"),
- "img": "fa fa-share-alt",
- "url": reverse("admin:domain_export"),
- "modal": True,
- "modalcb": "admin.exportform_cb"}
- ]
-
- return render_to_string('common/menulist.html', {
- "entries": entries,
- "selection": selection,
- "user": user
- })
-
-
-@register.simple_tag
-def identities_menu(user, selection=None):
- """Menu specific to the Identities page.
-
- :param ``User`` user: the connecter user
- :rtype: str
- :return: the rendered menu
- """
- entries = [
- {"name": "identities",
- "label": _("List identities"),
- "img": "fa fa-user",
- "class": "ajaxnav navigation",
- "url": "list/"},
- {"name": "quotas",
- "label": _("List quotas"),
- "img": "fa fa-hdd-o",
- "class": "ajaxnav navigation",
- "url": "quotas/"},
- {"name": "newaccount",
- "label": _("Add account"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "admin.newaccount_cb",
- "url": reverse("admin:account_add")},
- {"name": "newalias",
- "label": _("Add alias"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "admin.aliasform_cb",
- "url": reverse("admin:alias_add")},
- {"name": "newforward",
- "label": _("Add forward"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "admin.aliasform_cb",
- "url": reverse("admin:forward_add")},
- {"name": "newdlist",
- "label": _("Add distribution list"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "admin.aliasform_cb",
- "url": reverse("admin:dlist_add")},
- {"name": "import",
- "label": _("Import"),
- "img": "fa fa-folder-open",
- "url": reverse("admin:identity_import"),
- "modal": True,
- "modalcb": "admin.importform_cb"},
- {"name": "export",
- "label": _("Export"),
- "img": "fa fa-share-alt",
- "url": reverse("admin:identity_export"),
- "modal": True,
- "modalcb": "admin.exportform_cb"
- }
- ]
-
- return render_to_string('common/menulist.html', {
- "entries": entries,
- "user": user
- })
-
-
-@register.simple_tag
-def domain_actions(user, domain):
- actions = []
- if domain.__class__.__name__ == 'Domain':
- actions = [
- {"name": "listidentities",
- "url": "{0}#list/?searchquery=@{1}".format(
- reverse("admin:identity_list"), domain.name),
- "title": _("View the domain's identities"),
- "img": "fa fa-user"}
- ]
- if user.has_perm("admin.delete_domain"):
- actions.append({
- "name": "deldomain",
- "url": reverse("admin:domain_delete", args=[domain.id]),
- "title": _("Delete %s?" % domain.name),
- "img": "fa fa-trash"
- })
- else:
- actions = events.raiseQueryEvent('GetDomainActions', user, domain)
-
- return render_actions(actions)
-
-
-@register.simple_tag
-def identity_actions(user, ident):
- name = ident.__class__.__name__
- objid = ident.id
- if name == "User":
- actions = events.raiseQueryEvent("ExtraAccountActions", ident)
- actions += [
- {"name": "delaccount",
- "url": reverse("admin:account_delete", args=[objid]),
- "img": "fa fa-trash",
- "title": _("Delete %s?" % ident.username)},
- ]
- else:
- actions = [
- {"name": "delalias",
- "url": reverse("admin:alias_delete") + "?selection=%s" % objid,
- "img": "fa fa-trash",
- "title": _("Delete %s?" % ident.full_address)},
- ]
- return render_actions(actions)
-
-
-@register.assignment_tag
-def check_identity_status(identity):
- """Check if identity is enabled or not."""
- if identity.__class__.__name__ == "User":
- if identity.mailbox_set.count() \
- and not identity.mailbox_set.all()[0].domain.enabled:
- return False
- elif not identity.is_active:
- return False
- elif not identity.enabled or not identity.domain.enabled:
- return False
- return True
-
-
-@register.simple_tag
-def domain_modify_link(domain):
- linkdef = {"label": domain.name, "modal": True}
- if domain.__class__.__name__ == "Domain":
- linkdef["url"] = reverse("admin:domain_change", args=[domain.id])
- linkdef["modalcb"] = "admin.domainform_cb"
- else:
- tmp = events.raiseDictEvent('GetDomainModifyLink', domain)
- for key in ['url', 'modalcb']:
- linkdef[key] = tmp[key]
- return render_link(linkdef)
-
-
-@register.simple_tag
-def domain_aliases(domain):
- """Display domain aliases of this domain.
-
- :param domain:
- :rtype: str
- """
- if not domain.aliases.count():
- return '---'
- res = ''
- for alias in domain.aliases.all():
- res += '%s ' % alias.name
- return res
-
-
-@register.simple_tag
-def identity_modify_link(identity, active_tab='default'):
- """Return the appropriate modification link.
-
- According to the identity type, a specific modification link (URL)
- must be used.
-
- :param identity: a ``User`` or ``Alias`` instance
- :param str active_tab: the tab to display
- :rtype: str
- """
- linkdef = {"label": identity.identity, "modal": True}
- if identity.__class__.__name__ == "User":
- linkdef["url"] = reverse("admin:account_change", args=[identity.id])
- linkdef["url"] += "?active_tab=%s" % active_tab
- linkdef["modalcb"] = "admin.editaccount_cb"
- else:
- linkdef["url"] = reverse("admin:alias_change", args=[identity.id])
- linkdef["modalcb"] = "admin.aliasform_cb"
- return render_link(linkdef)
-
-
-@register.simple_tag
-def domadmin_actions(daid, domid):
- actions = [{
- "name": "removeperm",
- "url": "{0}?domid={1}&daid={2}".format(
- reverse("admin:permission_remove"), domid, daid),
- "img": "fa fa-trash",
- "title": _("Remove this permission")
- }]
- return render_actions(actions)
-
-
-@register.filter
-def gender(value, target):
- if value in genders:
- trans = target == "m" and genders[value][0] or genders[value][1]
- if trans.find("_") == -1:
- return trans
- return value
-
-
-@register.simple_tag
-def get_extra_admin_content(user, target, currentpage):
- res = events.raiseQueryEvent(
- "ExtraAdminContent", user, target, currentpage
- )
- return "".join(res)
diff --git a/modoboa/extensions/admin/tests/__init__.py b/modoboa/extensions/admin/tests/__init__.py
deleted file mode 100644
index 8fc7ac21f..000000000
--- a/modoboa/extensions/admin/tests/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from .domain import DomainTestCase
-from .domain_alias import DomainAliasTestCase
-from .account import AccountTestCase, PermissionsTestCase
-from .alias import AliasTestCase
-from .import_ import ImportTestCase
-from .export import ExportTestCase
-from .password_schemes import PasswordSchemesTestCase
-from .user import ForwardTestCase
-
-__all__ = [
- 'DomainTestCase', 'DomainAliasTestCase', 'AccountTestCase',
- 'PermissionsTestCase', 'AliasTestCase', 'ImportTestCase',
- 'ExportTestCase', 'PasswordSchemesTestCase', 'ForwardTestCase'
-]
diff --git a/modoboa/extensions/admin/tests/account.py b/modoboa/extensions/admin/tests/account.py
deleted file mode 100644
index 6881056a4..000000000
--- a/modoboa/extensions/admin/tests/account.py
+++ /dev/null
@@ -1,197 +0,0 @@
-from django.core.urlresolvers import reverse
-
-from modoboa.core.models import User
-from modoboa.extensions.admin import factories
-from modoboa.extensions.admin.models import (
- Domain, Mailbox
-)
-from modoboa.lib.tests import ModoTestCase
-
-
-class AccountTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(AccountTestCase, self).setUp()
- factories.populate_database()
-
- def test_crud(self):
- values = dict(
- username="tester@test.com", first_name="Tester", last_name="Toto",
- password1="toto", password2="toto", role="SimpleUsers",
- quota_act=True,
- is_active=True, email="tester@test.com", stepid='step2'
- )
- self.ajax_post(reverse("admin:account_add"), values)
-
- account = User.objects.get(username="tester@test.com")
- mb = account.mailbox_set.all()[0]
- self.assertEqual(mb.full_address, "tester@test.com")
- self.assertEqual(mb.quota, 10)
- self.assertEqual(mb.enabled, True)
- self.assertEqual(mb.quota_value.username, "tester@test.com")
- self.assertEqual(account.username, mb.full_address)
- self.assertTrue(account.check_password("toto"))
- self.assertEqual(account.first_name, "Tester")
- self.assertEqual(account.last_name, "Toto")
- self.assertEqual(mb.domain.mailbox_count, 3)
-
- values["username"] = "pouet@test.com"
- self.ajax_post(
- reverse("admin:account_change", args=[account.id]), values
- )
- mb = Mailbox.objects.get(pk=mb.id)
- self.assertEqual(mb.full_address, "pouet@test.com")
- self.assertEqual(mb.quota_value.username, "pouet@test.com")
- self.ajax_post(
- reverse("admin:account_delete", args=[account.id]), {}
- )
-
- def _set_quota(self, email, value, expected_status=200):
- account = User.objects.get(username=email)
- values = {
- "username": email, "role": "SimpleUsers", "quota_act": False,
- "is_active": True, "quota": value, "email": email
- }
- self.ajax_post(
- reverse("admin:account_change", args=[account.id]),
- values, status=expected_status
- )
-
- def test_set_nul_quota_as_superadmin(self):
- self._set_quota("user@test.com", 0)
-
- def test_set_nul_quota_as_domainadmin(self):
- self.clt.logout()
- self.assertTrue(
- self.clt.login(username="admin@test.com", password="toto")
- )
- self._set_quota("user@test.com", 0, 400)
- self.clt.logout()
- self.assertTrue(
- self.clt.login(username="admin@test2.com", password="toto")
- )
- self._set_quota("user@test2.com", 0)
-
-
-class PermissionsTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(PermissionsTestCase, self).setUp()
- factories.populate_database()
- self.user = User.objects.get(username='user@test.com')
- self.values = dict(
- username=self.user.username, role="DomainAdmins",
- is_active=self.user.is_active, email="user@test.com",
- quota_act=True
- )
-
- def tearDown(self):
- self.clt.logout()
-
- def test_domain_admins(self):
- self.ajax_post(
- reverse("admin:account_change", args=[self.user.id]),
- self.values
- )
- self.assertEqual(self.user.group, "DomainAdmins")
-
- self.values["role"] = "SimpleUsers"
- self.ajax_post(
- reverse("admin:account_change", args=[self.user.id]),
- self.values
- )
- self.assertNotEqual(self.user.group, 'DomainAdmins')
-
- def test_superusers(self):
- self.values["role"] = "SuperAdmins"
- self.ajax_post(
- reverse("admin:account_change", args=[self.user.id]),
- self.values
- )
- self.assertEqual(
- User.objects.get(username="user@test.com").is_superuser, True
- )
-
- self.values["role"] = "SimpleUsers"
- self.ajax_post(
- reverse("admin:account_change", args=[self.user.id]),
- self.values
- )
- self.assertEqual(User.objects.get(
- username="user@test.com").is_superuser, False)
-
- def test_self_modif(self):
- self.clt.logout()
- self.assertTrue(
- self.clt.login(username="admin@test.com", password="toto")
- )
- admin = User.objects.get(username="admin@test.com")
- values = dict(
- username="admin@test.com", first_name="Admin",
- password1="", password2="",
- quota=10, is_active=True, email="admin@test.com"
- )
- self.ajax_post(
- reverse("admin:account_change", args=[admin.id]),
- values
- )
- self.assertEqual(admin.group, "DomainAdmins")
- self.assertTrue(admin.can_access(Domain.objects.get(name="test.com")))
-
- values["role"] = "SuperAdmins"
- self.ajax_post(
- reverse("admin:account_change", args=[admin.id]),
- values
- )
- admin = User.objects.get(username="admin@test.com")
- self.assertEqual(admin.group, "DomainAdmins")
-
- def test_domadmin_access(self):
- self.clt.logout()
- self.assertEqual(
- self.clt.login(username="admin@test.com", password="toto"),
- True)
- response = self.clt.get(reverse("admin:domain_list"))
- self.assertEqual(response.status_code, 200)
-
- response = self.clt.get(
- reverse("admin:account_change", args=[self.user.id]),
- HTTP_X_REQUESTED_WITH='XMLHttpRequest')
- self.assertNotEqual(response["Content-Type"], "application/json")
-
- def test_domainadmin_deletes_superadmin(self):
- """Check domain admins restrictions about super admins
-
- When a super admin owns a mailbox and a domain admin exists
- for the associated domain, this domain admin must not be able
- to access the super admin.
- """
- values = dict(
- username="superadmin2@test.com", first_name="Super",
- last_name="Admin", password1="toto", password2="toto",
- role="SuperAdmins", is_active=True,
- email="superadmin2@test.com", stepid='step2'
- )
- self.ajax_post(
- reverse("admin:account_add"),
- values
- )
- account = User.objects.get(username="superadmin2@test.com")
- self.clt.logout()
- self.clt.login(username="admin@test.com", password="toto")
- self.ajax_post(
- reverse("admin:account_delete", args=[account.id]), {}, 403
- )
-
- def test_domainadmin_dlist_local_domain_not_owned(self):
- """Check if a domain admin can use a local mailbox he can't
- access as a recipient in a distribution list"""
- values = dict(
- email="all@test.com",
- recipients="user@test.com",
- recipients_1="user@test2.com",
- enabled=True
- )
- self.ajax_post(reverse("admin:dlist_add"), values)
diff --git a/modoboa/extensions/admin/tests/alias.py b/modoboa/extensions/admin/tests/alias.py
deleted file mode 100644
index dbf6c3b90..000000000
--- a/modoboa/extensions/admin/tests/alias.py
+++ /dev/null
@@ -1,130 +0,0 @@
-from django.core.urlresolvers import reverse
-
-from modoboa.core.models import User
-from modoboa.extensions.admin import factories
-from modoboa.extensions.admin.models import (
- Alias
-)
-from modoboa.lib.tests import ModoTestCase
-
-
-class AliasTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(AliasTestCase, self).setUp()
- factories.populate_database()
-
- def test_alias(self):
- user = User.objects.get(username="user@test.com")
- values = dict(
- username="user@test.com", role=user.group,
- is_active=user.is_active, email="user@test.com",
- aliases="toto@test.com", aliases_1="titi@test.com"
- )
- self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values
- )
- self.assertEqual(user.mailbox_set.all()[0].alias_set.count(), 2)
-
- del values["aliases_1"]
- self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values
- )
- self.assertEqual(user.mailbox_set.all()[0].alias_set.count(), 1)
-
- def test_upper_case_alias(self):
- """Try to create an upper case alias."""
- user = User.objects.get(username="user@test.com")
- values = dict(
- username="user@test.com", role=user.group,
- is_active=user.is_active, email="user@test.com",
- aliases="Toto@test.com"
- )
- self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values
- )
- self.assertEqual(user.mailbox_set.first().alias_set.count(), 1)
- self.assertEqual(
- user.mailbox_set.first().alias_set.first(), "toto@test.com")
-
- values = {
- "email": "Titi@test.com", "recipient": "user@test.com",
- "enabled": True
- }
- self.ajax_post(reverse("admin:alias_add"), values)
- self.assertEqual(
- user.mailbox_set.first().alias_set.first(), "titi@test.com")
-
- def test_dlist(self):
- values = dict(email="all@test.com",
- recipients="user@test.com",
- recipients_1="admin@test.com",
- recipients_2="ext@titi.com",
- enabled=True)
- self.ajax_post(
- reverse("admin:dlist_add"), values
- )
- user = User.objects.get(username="user@test.com")
- self.assertEqual(user.mailbox_set.all()[0].alias_set.count(), 2)
- admin = User.objects.get(username="admin@test.com")
- self.assertEqual(admin.mailbox_set.all()[0].alias_set.count(), 1)
-
- dlist = Alias.objects.get(address="all", domain__name="test.com")
- self.assertEqual(len(dlist.get_recipients()), 3)
- del values["recipients_1"]
- self.ajax_post(
- reverse("admin:alias_change", args=[dlist.id]),
- values
- )
- self.assertEqual(dlist.get_recipients_count(), 2)
-
- self.ajax_post(
- reverse("admin:alias_delete") + "?selection=%d" % dlist.id, {}
- )
- self.assertRaises(Alias.DoesNotExist, Alias.objects.get,
- address="all", domain__name="test.com")
-
- def test_forward(self):
- values = dict(email="forward2@test.com", recipients="rcpt@dest.com")
- self.ajax_post(
- reverse("admin:forward_add"), values
- )
- fwd = Alias.objects.get(address="forward2", domain__name="test.com")
- self.assertEqual(fwd.get_recipients_count(), 1)
-
- values["recipients"] = "rcpt2@dest.com"
- self.ajax_post(
- reverse("admin:alias_change",
- args=[fwd.id]),
- values
- )
- self.assertEqual(fwd.get_recipients_count(), 1)
-
- self.ajax_post(
- reverse("admin:alias_delete") + "?selection=%d"
- % fwd.id, {}
- )
- self.assertRaises(Alias.DoesNotExist, Alias.objects.get,
- address="forward2", domain__name="test.com")
-
- def test_forward_and_local_copies(self):
- values = dict(email="user@test.com", recipients="rcpt@dest.com")
- self.ajax_post(
- reverse("admin:forward_add"), values
- )
- fwd = Alias.objects.get(address="user", domain__name="test.com")
- self.assertEqual(fwd.get_recipients_count(), 1)
-
- values["recipients"] = "rcpt@dest.com"
- values["recipients_1"] = "user@test.com"
- self.ajax_post(
- reverse("admin:alias_change", args=[fwd.id]),
- values
- )
- fwd = Alias.objects.get(pk=fwd.pk)
- self.assertEqual(fwd.get_recipients_count(), 2)
- self.assertEqual(fwd.aliases.count(), 0)
diff --git a/modoboa/extensions/admin/tests/domain.py b/modoboa/extensions/admin/tests/domain.py
deleted file mode 100644
index 3c6cd739a..000000000
--- a/modoboa/extensions/admin/tests/domain.py
+++ /dev/null
@@ -1,112 +0,0 @@
-from django.core.urlresolvers import reverse
-from modoboa.core.models import User
-from modoboa.lib import parameters
-from modoboa.lib.tests import ModoTestCase
-from modoboa.extensions.admin.models import (
- Domain, Alias
-)
-from modoboa.extensions.admin import factories
-
-
-class DomainTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(DomainTestCase, self).setUp()
- factories.populate_database()
-
- def test_create(self):
- """Test the creation of a domain
- """
- values = {
- "name": "pouet.com", "quota": 100, "create_dom_admin": "no",
- "stepid": 'step2'
- }
- self.ajax_post(reverse("admin:domain_add"), values)
- dom = Domain.objects.get(name="pouet.com")
- self.assertEqual(dom.name, "pouet.com")
- self.assertEqual(dom.quota, 100)
- self.assertEqual(dom.enabled, False)
- self.assertFalse(dom.admins)
-
- def test_create_with_template(self):
- """Test the creation of a domain with a template
-
- """
- values = {
- "name": "pouet.com", "quota": 100, "create_dom_admin": "yes",
- "dom_admin_username": "toto", "create_aliases": "yes",
- "stepid": 'step2'
- }
- self.ajax_post(
- reverse("admin:domain_add"),
- values
- )
- dom = Domain.objects.get(name="pouet.com")
- da = User.objects.get(username="toto@pouet.com")
- self.assertIn(da, dom.admins)
- al = Alias.objects.get(address="postmaster", domain__name="pouet.com")
- self.assertIn(da.mailbox_set.all()[0], al.mboxes.all())
- self.assertTrue(da.can_access(al))
-
- def test_create_with_template_and_empty_quota(self):
- """Test the creation of a domain with a template and no quota"""
- values = {
- "name": "pouet.com", "quota": 0, "create_dom_admin": "yes",
- "dom_admin_username": "toto", "create_aliases": "yes",
- "stepid": 'step2'
- }
- self.ajax_post(
- reverse("admin:domain_add"),
- values
- )
- dom = Domain.objects.get(name="pouet.com")
- da = User.objects.get(username="toto@pouet.com")
- self.assertIn(da, dom.admins)
- al = Alias.objects.get(address="postmaster", domain__name="pouet.com")
- self.assertIn(da.mailbox_set.all()[0], al.mboxes.all())
- self.assertTrue(da.can_access(al))
-
- def test_create_using_default_quota(self):
- parameters.save_admin('DEFAULT_DOMAIN_QUOTA', 50, app='admin')
- values = {
- "name": "pouet.com", "create_dom_admin": "yes",
- "dom_admin_username": "toto", "create_aliases": "yes",
- "stepid": 'step2'
- }
- self.ajax_post(
- reverse("admin:domain_add"),
- values
- )
- dom = Domain.objects.get(name="pouet.com")
- self.assertEqual(dom.quota, 50)
- da = User.objects.get(username="toto@pouet.com")
- self.assertEqual(da.mailbox_set.all()[0].quota, 50)
-
- def test_modify(self):
- """Test the modification of a domain
-
- Rename 'test.com' domain to 'pouet.com'
- """
- values = {
- "name": "pouet.com", "quota": 100, "enabled": True
- }
- dom = Domain.objects.get(name="test.com")
- self.ajax_post(
- reverse("admin:domain_change", args=[dom.id]),
- values
- )
- dom = Domain.objects.get(name="pouet.com")
- self.assertEqual(dom.name, "pouet.com")
- self.assertTrue(dom.enabled)
-
- def test_delete(self):
- """Test the removal of a domain
- """
- dom = Domain.objects.get(name="test.com")
- self.ajax_post(
- reverse("admin:domain_delete", args=[dom.id]),
- {}
- )
- with self.assertRaises(Domain.DoesNotExist):
- Domain.objects.get(pk=1)
diff --git a/modoboa/extensions/admin/tests/domain_alias.py b/modoboa/extensions/admin/tests/domain_alias.py
deleted file mode 100644
index a13abc915..000000000
--- a/modoboa/extensions/admin/tests/domain_alias.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from django.core.urlresolvers import reverse
-from modoboa.lib.tests import ModoTestCase
-from modoboa.extensions.admin.models import (
- Domain, DomainAlias
-)
-from modoboa.extensions.admin import factories
-
-
-class DomainAliasTestCase(ModoTestCase):
- fixtures = ['initial_users.json']
-
- def setUp(self):
- super(DomainAliasTestCase, self).setUp()
- factories.populate_database()
- self.dom = Domain.objects.get(name='test.com')
-
- def test_model(self):
- dom = Domain.objects.get(name="test.com")
- domal = DomainAlias()
- domal.name = "domalias.net"
- domal.target = dom
- domal.save()
- self.assertEqual(dom.domainalias_count, 1)
-
- domal.name = "domalias.org"
- domal.save()
-
- domal.delete()
-
- def test_form(self):
- dom = Domain.objects.get(name="test.com")
- values = dict(name=dom.name, quota=dom.quota, enabled=dom.enabled,
- aliases="domalias.net", aliases_1="domalias.com")
- self.ajax_post(
- reverse("admin:domain_change",
- args=[dom.id]),
- values
- )
- self.assertEqual(dom.domainalias_set.count(), 2)
-
- del values["aliases_1"]
- self.ajax_post(
- reverse("admin:domain_change",
- args=[dom.id]),
- values
- )
- self.assertEqual(dom.domainalias_set.count(), 1)
diff --git a/modoboa/extensions/admin/tests/export.py b/modoboa/extensions/admin/tests/export.py
deleted file mode 100644
index ca95c4b7d..000000000
--- a/modoboa/extensions/admin/tests/export.py
+++ /dev/null
@@ -1,84 +0,0 @@
-from django.core.urlresolvers import reverse
-
-from modoboa.extensions.admin import factories
-from modoboa.lib.tests import ModoTestCase
-
-
-class ExportTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(ExportTestCase, self).setUp()
- factories.populate_database()
-
- def __export_identities(self, idtfilter="", grpfilter=""):
- self.clt.get(
- reverse("admin:_identity_list")
- + "?grpfilter=%s&idtfilter=%s" % (grpfilter, idtfilter)
- )
- return self.clt.post(
- reverse("admin:identity_export"),
- {"filename": "test.csv"}
- )
-
- def assertListEqual(self, list1, list2):
- list2 = list2.split('\r\n')
- for entry in list1.split('\r\n'):
- if not entry:
- continue
- self.assertIn(entry, list2)
-
- def test_export_identities(self):
- response = self.__export_identities()
- self.assertListEqual(
- "account;admin;{CRYPT}dTTsGDkA5ZHKg;;;True;SuperAdmins;;\r\naccount;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com\r\naccount;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\nalias;alias@test.com;True;user@test.com\r\nforward;forward@test.com;True;user@external.com\r\ndlist;postmaster@test.com;True;toto@titi.com;test@truc.fr\r\n",
- response.content.strip()
- )
-
- def test_export_simpleusers(self):
- response = self.__export_identities(
- idtfilter="account", grpfilter="SimpleUsers"
- )
- self.assertListEqual(
- "account;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10",
- response.content.strip()
- )
-
- def test_export_superadmins(self):
- response = self.__export_identities(
- idtfilter="account", grpfilter="SuperAdmins"
- )
- self.assertEqual(
- response.content.strip(),
- "account;admin;{CRYPT}dTTsGDkA5ZHKg;;;True;SuperAdmins;;"
- )
-
- def test_export_domainadmins(self):
- response = self.__export_identities(
- idtfilter="account", grpfilter="DomainAdmins"
- )
- self.assertListEqual(
- "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com",
- response.content.strip()
- )
-
- def test_export_aliases(self):
- response = self.__export_identities(idtfilter="alias")
- self.assertEqual(
- response.content.strip(),
- "alias;alias@test.com;True;user@test.com"
- )
-
- def test_export_forwards(self):
- response = self.__export_identities(idtfilter="forward")
- self.assertEqual(
- response.content.strip(),
- "forward;forward@test.com;True;user@external.com"
- )
-
- def test_export_dlists(self):
- response = self.__export_identities(idtfilter="dlist")
- self.assertEqual(
- response.content.strip(),
- "dlist;postmaster@test.com;True;toto@titi.com;test@truc.fr"
- )
diff --git a/modoboa/extensions/admin/tests/import_.py b/modoboa/extensions/admin/tests/import_.py
deleted file mode 100644
index dee11d995..000000000
--- a/modoboa/extensions/admin/tests/import_.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# coding: utf-8
-from django.core.files.base import ContentFile
-from django.core.urlresolvers import reverse
-
-from modoboa.core.models import User
-from modoboa.extensions.admin import factories
-from modoboa.extensions.admin.models import (
- Domain, Alias, DomainAlias
-)
-from modoboa.lib.tests import ModoTestCase
-
-
-class ImportTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(ImportTestCase, self).setUp()
- factories.populate_database()
-
- def test_domains_import(self):
- f = ContentFile(b"""domain; domain1.com; 100; True
-domain; domain2.com; 200; False
-domainalias; domalias1.com; domain1.com; True
-""", name="domains.csv")
- self.clt.post(
- reverse("admin:domain_import"), {
- "sourcefile": f
- }
- )
- admin = User.objects.get(username="admin")
- dom = Domain.objects.get(name="domain1.com")
- self.assertEqual(dom.quota, 100)
- self.assertTrue(dom.enabled)
- self.assertTrue(admin.is_owner(dom))
- domalias = DomainAlias.objects.get(name="domalias1.com")
- self.assertEqual(domalias.target, dom)
- self.assertTrue(dom.enabled)
- self.assertTrue(admin.is_owner(domalias))
- dom = Domain.objects.get(name="domain2.com")
- self.assertEqual(dom.quota, 200)
- self.assertFalse(dom.enabled)
- self.assertTrue(admin.is_owner(dom))
-
- def test_import_domains_with_conflict(self):
- f = ContentFile(b"""domain;test.alias;10;True
-domainalias;test.alias;test.com;True
-""", name="domains.csv")
- resp = self.clt.post(
- reverse("admin:domain_import"), {
- "sourcefile": f
- }
- )
- self.assertIn('Object already exists: domainalias', resp.content)
-
- def test_identities_import(self):
- f = ContentFile(b"""
-account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; 0
-account; truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 5; test.com
-alias; alias1@test.com; True; user1@test.com
-forward; fwd1@test.com; True; user@extdomain.com
-dlist; dlist@test.com; True; user1@test.com; user@extdomain.com
-""", name="identities.csv")
- self.clt.post(
- reverse("admin:identity_import"),
- {"sourcefile": f, "crypt_password": True}
- )
- admin = User.objects.get(username="admin")
- u1 = User.objects.get(username="user1@test.com")
- mb1 = u1.mailbox_set.all()[0]
- self.assertTrue(admin.is_owner(u1))
- self.assertEqual(u1.email, "user1@test.com")
- self.assertEqual(u1.first_name, "User")
- self.assertEqual(u1.last_name, "One")
- self.assertTrue(u1.is_active)
- self.assertEqual(u1.group, "SimpleUsers")
- self.assertTrue(mb1.use_domain_quota)
- self.assertEqual(mb1.quota, 0)
- self.assertTrue(admin.is_owner(mb1))
- self.assertEqual(mb1.full_address, "user1@test.com")
- self.assertTrue(
- self.clt.login(username="user1@test.com", password="toto")
- )
-
- da = User.objects.get(username="truc@test.com")
- damb = da.mailbox_set.all()[0]
- self.assertEqual(da.first_name, u"René")
- self.assertEqual(da.group, "DomainAdmins")
- self.assertEqual(damb.quota, 5)
- self.assertFalse(damb.use_domain_quota)
- self.assertEqual(damb.full_address, "truc@test.com")
- dom = Domain.objects.get(name="test.com")
- self.assertIn(da, dom.admins)
- u = User.objects.get(username="user@test.com")
- self.assertTrue(da.can_access(u))
-
- al = Alias.objects.get(address="alias1", domain__name="test.com")
- self.assertIn(u1.mailbox_set.all()[0], al.mboxes.all())
- self.assertTrue(admin.is_owner(al))
-
- fwd = Alias.objects.get(address="fwd1", domain__name="test.com")
- self.assertIn("user@extdomain.com", fwd.extmboxes)
- self.assertTrue(admin.is_owner(fwd))
-
- dlist = Alias.objects.get(address="dlist", domain__name="test.com")
- self.assertIn(u1.mailbox_set.all()[0], dlist.mboxes.all())
- self.assertIn("user@extdomain.com", dlist.extmboxes)
- self.assertTrue(admin.is_owner(dlist))
-
- def test_import_invalid_quota(self):
- f = ContentFile(b"""
-account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; ; test.com
-""", name="identities.csv")
- resp = self.clt.post(
- reverse("admin:identity_import"),
- {"sourcefile": f, "crypt_password": True}
- )
- self.assertIn('wrong quota value', resp.content)
-
- def test_import_quota_too_big(self):
- self.clt.logout()
- self.clt.login(username="admin@test.com", password="toto")
- f = ContentFile(b"""
-account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; 20
-""", name="identities.csv")
- resp = self.clt.post(
- reverse("admin:identity_import"),
- {"sourcefile": f, "crypt_password": True}
- )
- self.assertIn('Quota is greater than the allowed', resp.content)
-
- def test_import_missing_quota(self):
- f = ContentFile(b"""
-account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com
-""", name="identities.csv")
- resp = self.clt.post(
- reverse("admin:identity_import"),
- {"sourcefile": f, "crypt_password": True}
- )
- account = User.objects.get(username="user1@test.com")
- self.assertEqual(
- account.mailbox_set.all()[0].quota,
- account.mailbox_set.all()[0].domain.quota
- )
-
- def test_import_duplicate(self):
- f = ContentFile(b"""
-account; admin@test.com; toto; Admin; ; True; DomainAdmins; admin@test.com; 0; test.com
-account; truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 0; test.com
-""", name="identities.csv")
- self.clt.post(
- reverse("admin:identity_import"),
- {"sourcefile": f, "crypt_password": True,
- "continue_if_exists": True}
- )
- admin = User.objects.get(username="admin")
- u1 = User.objects.get(username="truc@test.com")
- self.assertTrue(admin.is_owner(u1))
-
- def test_import_superadmin(self):
- """Check if a domain admin can import a superadmin
-
- Expected result: no
- """
- self.clt.logout()
- self.assertTrue(
- self.clt.login(username="admin@test.com", password="toto")
- )
- f = ContentFile(b"""
-account; sa@test.com; toto; Super; Admin; True; SuperAdmins; superadmin@test.com; 50
-""", name="identities.csv")
- self.clt.post(
- reverse("admin:identity_import"),
- {"sourcefile": f, "crypt_password": True,
- "continue_if_exists": True}
- )
- with self.assertRaises(User.DoesNotExist):
- User.objects.get(username="sa@test.com")
-
- def test_import_alias_with_empty_values(self):
- f = ContentFile(b"""
-alias;user.alias@test.com;True;user@test.com;;;;;;;;;;;;;;;;
-""", name="identities.csv")
- self.clt.post(
- reverse("admin:identity_import"),
- {"sourcefile": f, "crypt_password": True,
- "continue_if_exists": True}
- )
- alias = Alias.objects.get(
- domain__name="test.com", address="user.alias"
- )
- self.assertEqual(alias.type, "alias")
diff --git a/modoboa/extensions/admin/tests/password_schemes.py b/modoboa/extensions/admin/tests/password_schemes.py
deleted file mode 100644
index 413d43651..000000000
--- a/modoboa/extensions/admin/tests/password_schemes.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from django.core.urlresolvers import reverse
-from modoboa.core import load_core_settings
-from modoboa.core.models import User
-from modoboa.lib.tests import ModoTestCase
-from modoboa.lib import parameters
-from modoboa.extensions.admin import factories
-
-
-class PasswordSchemesTestCase(ModoTestCase):
- fixtures = ['initial_users.json']
-
- def setUp(self):
- super(PasswordSchemesTestCase, self).setUp()
- factories.populate_database()
- load_core_settings()
-
- def _create_account(self):
- values = dict(
- username="tester@test.com", first_name="Tester", last_name="Toto",
- password1="toto", password2="toto", role="SimpleUsers",
- quota_act=True,
- is_active=True, email="tester@test.com", stepid='step2'
- )
- self.ajax_post(
- reverse("admin:account_add"),
- values
- )
-
- def _test_scheme(self, name, startpattern):
- parameters.save_admin('PASSWORD_SCHEME', name, app='core')
- self._create_account()
- account = User.objects.get(username='tester@test.com')
- self.assertTrue(account.password.startswith(startpattern))
- self.assertTrue(account.check_password('toto'))
-
- def test_sha512crypt_scheme(self):
- self._test_scheme('sha512crypt', '{SHA512-CRYPT}')
-
- def test_sha256crypt_scheme(self):
- self._test_scheme('sha256crypt', '{SHA256-CRYPT}')
-
- def test_md5crypt_scheme(self):
- self._test_scheme('md5crypt', '{MD5-CRYPT}')
-
- def test_sha256_scheme(self):
- self._test_scheme('sha256', '{SHA256}')
-
- def test_md5_scheme(self):
- self._test_scheme('md5', '{MD5}')
-
- def test_crypt(self):
- self._test_scheme('crypt', '{CRYPT}')
-
- def test_plain(self):
- self._test_scheme('plain', '{PLAIN}')
diff --git a/modoboa/extensions/admin/tests/user.py b/modoboa/extensions/admin/tests/user.py
deleted file mode 100644
index 173d03026..000000000
--- a/modoboa/extensions/admin/tests/user.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from django.core.urlresolvers import reverse
-from modoboa.core.models import User
-from modoboa.lib.tests import ModoTestCase
-from modoboa.extensions.admin.factories import populate_database
-from modoboa.extensions.admin.models import Alias
-
-
-class ForwardTestCase(ModoTestCase):
- fixtures = ['initial_users.json']
-
- def setUp(self):
- super(ForwardTestCase, self).setUp()
- populate_database()
-
- def test_forward_permissions(self):
- self.clt.logout()
- self.clt.login(username='user@test.com', password='toto')
- self.ajax_post(
- reverse('user_forward'),
- {'dest': 'user@extdomain.com', 'keepcopies': True}
- )
- forward = Alias.objects.get(address='user', domain__name='test.com')
- sadmin = User.objects.get(username='admin')
- self.assertTrue(sadmin.can_access(forward))
- domadmin = User.objects.get(username='admin@test.com')
- self.assertTrue(domadmin.can_access(forward))
diff --git a/modoboa/extensions/admin/urls.py b/modoboa/extensions/admin/urls.py
deleted file mode 100644
index e601c45d1..000000000
--- a/modoboa/extensions/admin/urls.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from django.conf.urls import patterns, url
-
-
-urlpatterns = patterns(
- 'modoboa.extensions.admin.views.domain',
-
- url(r'^$', 'index', name="index"),
- url(r'^domains/$', 'domains', name="domain_list"),
- url(r'^domains/list/$', '_domains', name="_domain_list"),
- url(r'^domains/flatlist/$', 'domains_list', name="domain_flat_list"),
- url(r'^domains/stats/$', 'domain_statistics', name="domain_statistics"),
- url(r'^domains/new/', 'newdomain', name='domain_add'),
- url(r'^domains/(?P\d+)/edit/$', 'editdomain', name="domain_change"),
- url(r'^domains/(?P\d+)/delete/$', 'deldomain',
- name="domain_delete"),
-)
-
-urlpatterns += patterns(
- 'modoboa.extensions.admin.views.identity',
-
- url(r'^permissions/remove/$', 'remove_permission',
- name="permission_remove"),
-
- url(r'^identities/$', 'identities', name="identity_list"),
- url(r'^identities/list/$', '_identities', name="_identity_list"),
- url(r'^identities/quotas/$', 'list_quotas', name="quota_list"),
- url(r'^identities/page/$', 'get_next_page', name="identity_page"),
-
- url(r'^accounts/list/$', 'accounts_list', name="account_list"),
- url(r'^accounts/new/$', 'newaccount', name="account_add"),
- url(r'^accounts/edit/(?P\d+)/$', 'editaccount',
- name="account_change"),
- url(r'^accounts/delete/(?P\d+)/$', 'delaccount',
- name="account_delete"),
-)
-
-urlpatterns += patterns(
- 'modoboa.extensions.admin.views.alias',
-
- url(r'^distriblists/new/$', 'newdlist', name="dlist_add"),
- url(r'^forwards/new/$', 'newforward', name="forward_add"),
-
- url(r'^aliases/new/$', 'newalias', name="alias_add"),
- url(r'^aliases/edit/(?P\d+)/$', 'editalias', name="alias_change"),
- url(r'^aliases/delete/$', 'delalias', name="alias_delete"),
-)
-
-urlpatterns += patterns(
- 'modoboa.extensions.admin.views.import',
-
- url(r'^domains/import/$', 'import_domains', name="domain_import"),
- url(r'^identities/import/$', 'import_identities', name="identity_import"),
-)
-
-urlpatterns += patterns(
- 'modoboa.extensions.admin.views.export',
-
- url(r'^domains/export/$', 'export_domains', name="domain_export"),
- url(r'^identities/export/$', 'export_identities', name="identity_export"),
-)
diff --git a/modoboa/extensions/admin/views/__init__.py b/modoboa/extensions/admin/views/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/admin/views/alias.py b/modoboa/extensions/admin/views/alias.py
deleted file mode 100644
index 0104b667a..000000000
--- a/modoboa/extensions/admin/views/alias.py
+++ /dev/null
@@ -1,135 +0,0 @@
-import reversion
-from django.db import IntegrityError
-from django.utils.translation import ugettext as _, ungettext
-from django.shortcuts import render
-from django.core.urlresolvers import reverse
-from django.contrib.auth.decorators import (
- login_required, permission_required
-)
-from modoboa.lib import events
-from modoboa.lib.web_utils import render_to_json_response
-from modoboa.lib.exceptions import PermDeniedException, Conflict
-from modoboa.extensions.admin.forms import AliasForm
-from modoboa.extensions.admin.models import Alias
-
-
-def _validate_alias(request, form, successmsg, callback=None):
- """Alias validation
-
- Common function shared between creation and modification actions.
- """
- if form.is_valid():
- form.set_recipients()
- try:
- alias = form.save()
- except IntegrityError:
- raise Conflict(_("Alias with this name already exists"))
- if callback:
- callback(request.user, alias)
- return render_to_json_response(successmsg)
-
- return render_to_json_response({'form_errors': form.errors}, status=400)
-
-
-def _new_alias(request, title, action, successmsg,
- tplname="admin/aliasform.html"):
- events.raiseEvent("CanCreate", request.user, "mailbox_aliases")
- if request.method == "POST":
- def callback(user, alias):
- alias.post_create(user)
-
- form = AliasForm(request.user, request.POST)
- return _validate_alias(
- request, form, successmsg, callback
- )
-
- ctx = {
- "title": title,
- "action": action,
- "formid": "aliasform",
- "action_label": _("Create"),
- "action_classes": "submit",
- "form": AliasForm(request.user)
- }
- return render(request, tplname, ctx)
-
-
-@login_required
-@permission_required("admin.add_alias")
-@reversion.create_revision()
-def newdlist(request):
- return _new_alias(
- request, _("New distribution list"), reverse("admin:dlist_add"),
- _("Distribution list created")
- )
-
-
-@login_required
-@permission_required("admin.add_alias")
-@reversion.create_revision()
-def newalias(request):
- return _new_alias(
- request, _("New alias"), reverse("admin:alias_add"),
- _("Alias created")
- )
-
-
-@login_required
-@permission_required("admin.add_alias")
-@reversion.create_revision()
-def newforward(request):
- return _new_alias(
- request, _("New forward"), reverse("admin:forward_add"),
- _("Forward created")
- )
-
-
-@login_required
-@permission_required("admin.change_alias")
-@reversion.create_revision()
-def editalias(request, alid, tplname="admin/aliasform.html"):
- alias = Alias.objects.get(pk=alid)
- if not request.user.can_access(alias):
- raise PermDeniedException
- if request.method == "POST":
- if len(alias.get_recipients()) >= 2:
- successmsg = _("Distribution list modified")
- elif alias.extmboxes != "":
- successmsg = _("Forward modified")
- else:
- successmsg = _("Alias modified")
- form = AliasForm(request.user, request.POST, instance=alias)
- return _validate_alias(request, form, successmsg)
-
- ctx = {
- 'action': reverse("admin:alias_change", args=[alias.id]),
- 'formid': 'aliasform',
- 'title': alias.full_address,
- 'action_label': _('Update'),
- 'action_classes': 'submit',
- 'form': AliasForm(request.user, instance=alias)
- }
- return render(request, tplname, ctx)
-
-
-@login_required
-@permission_required("admin.delete_alias")
-def delalias(request):
- selection = request.GET["selection"].split(",")
- for alid in selection:
- alias = Alias.objects.get(pk=alid)
- if not request.user.can_access(alias):
- raise PermDeniedException
- if alias.type == 'dlist':
- msg = "Distribution list deleted"
- msgs = "Distribution lists deleted"
- elif alias.type == 'forward':
- msg = "Forward deleted"
- msgs = "Forwards deleted"
- else:
- msg = "Alias deleted"
- msgs = "Aliases deleted"
- alias.delete()
-
- msg = ungettext(msg, msgs, len(selection))
- return render_to_json_response(msg)
diff --git a/modoboa/extensions/admin/views/domain.py b/modoboa/extensions/admin/views/domain.py
deleted file mode 100644
index 35ef6a68d..000000000
--- a/modoboa/extensions/admin/views/domain.py
+++ /dev/null
@@ -1,154 +0,0 @@
-"""
-Domain related views.
-"""
-
-from django.http import HttpResponseRedirect
-from django.utils.translation import ugettext as _, ungettext
-from django.core.urlresolvers import reverse
-from django.shortcuts import render
-from django.views.decorators.csrf import ensure_csrf_cookie
-from django.contrib.auth.decorators import (
- login_required, permission_required, user_passes_test
-)
-
-import reversion
-
-from modoboa.core.models import User
-from modoboa.lib import parameters, events
-from modoboa.lib.web_utils import (
- _render_to_string, render_to_json_response
-)
-from modoboa.lib.exceptions import (
- PermDeniedException
-)
-from modoboa.lib.listing import get_sort_order, get_listing_page
-from modoboa.extensions.admin.models import (
- Domain, DomainAlias, Mailbox, Alias
-)
-from modoboa.extensions.admin.forms import (
- DomainForm
-)
-from modoboa.extensions.admin.lib import get_domains
-
-
-@login_required
-def index(request):
- return HttpResponseRedirect(reverse("admin:domain_list"))
-
-
-@login_required
-@user_passes_test(
- lambda u: u.has_perm("admin.view_domains")
- or u.has_perm("admin.view_mailboxes")
-)
-def _domains(request):
- sort_order, sort_dir = get_sort_order(request.GET, "name")
- filters = dict(
- (flt, request.GET.get(flt, None))
- for flt in ['domfilter', 'searchquery']
- + events.raiseQueryEvent('ExtraDomainFilters')
- )
- request.session['domains_filters'] = filters
- domainlist = get_domains(request.user, **filters)
- if sort_order == 'name':
- domainlist = sorted(
- domainlist,
- key=lambda d: getattr(d, sort_order), reverse=sort_dir == '-'
- )
- else:
- domainlist = sorted(domainlist, key=lambda d: d.tags[0],
- reverse=sort_dir == '-')
- context = {
- "handle_mailboxes": parameters.get_admin(
- "HANDLE_MAILBOXES", raise_error=False),
- "auto_account_removal": parameters.get_admin("AUTO_ACCOUNT_REMOVAL")
- }
- page = get_listing_page(domainlist, request.GET.get("page", 1))
- if page is None:
- context["length"] = 0
- else:
- context["rows"] = _render_to_string(
- request, 'admin/domains_table.html', {
- 'domains': page.object_list,
- }
- )
- context["pages"] = [page.number]
- return render_to_json_response(context)
-
-
-@login_required
-@ensure_csrf_cookie
-def domains(request, tplname="admin/domains.html"):
- if not request.user.has_perm("admin.view_domains"):
- if request.user.has_perm("admin.view_mailboxes"):
- return HttpResponseRedirect(
- reverse("admin:identity_list")
- )
- return HttpResponseRedirect(reverse("core:user_index"))
- return render(request, tplname, {"selection": "domains"})
-
-
-@login_required
-@permission_required("core.add_user")
-def domains_list(request):
- doms = [dom.name for dom in Domain.objects.get_for_admin(request.user)]
- return render_to_json_response(doms)
-
-
-@login_required
-@permission_required("admin.add_domain")
-@reversion.create_revision()
-def newdomain(request):
- from modoboa.extensions.admin.forms import DomainWizard
-
- events.raiseEvent("CanCreate", request.user, "domains")
- return DomainWizard(request).process()
-
-
-@login_required
-@permission_required("admin.view_domains")
-@reversion.create_revision()
-def editdomain(request, dom_id):
- """Edit domain view."""
- domain = Domain.objects.get(pk=dom_id)
- if not request.user.can_access(domain):
- raise PermDeniedException
-
- instances = dict(general=domain)
- events.raiseEvent("FillDomainInstances", request.user, domain, instances)
- return DomainForm(request, instances=instances).process()
-
-
-@login_required
-@permission_required("admin.delete_domain")
-def deldomain(request, dom_id):
- keepdir = True if request.POST.get("keepdir", "false") == "true" else False
- try:
- mb = Mailbox.objects.get(user__id=request.user.id)
- except Mailbox.DoesNotExist:
- mb = None
-
- dom = Domain.objects.get(pk=dom_id)
- if not request.user.can_access(dom):
- raise PermDeniedException
- if mb and mb.domain == dom:
- raise PermDeniedException(_("You can't delete your own domain"))
- dom.delete(request.user, keepdir)
-
- msg = ungettext("Domain deleted", "Domains deleted", 1)
- return render_to_json_response(msg)
-
-
-@login_required
-@permission_required("admin.view_domains")
-def domain_statistics(request):
- """A simple page to present domain statistics."""
- context = {}
- if request.user.group == "SuperAdmins":
- context.update({
- "domains_counter": Domain.objects.count(),
- "domain_aliases_counter": DomainAlias.objects.count(),
- "identities_counter": User.objects.count() + Alias.objects.count(),
- })
- context.update({"domains": Domain.objects.get_for_admin(request.user)})
- return render(request, "admin/domain_statistics.html", context)
diff --git a/modoboa/extensions/admin/views/export.py b/modoboa/extensions/admin/views/export.py
deleted file mode 100644
index 38fe6494f..000000000
--- a/modoboa/extensions/admin/views/export.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""Export related views."""
-
-import cStringIO
-import csv
-
-from rfc6266 import build_header
-
-from django.contrib.auth.decorators import (
- login_required, permission_required, user_passes_test
-)
-from django.core.urlresolvers import reverse
-from django.http import HttpResponse
-from django.shortcuts import render
-from django.utils.translation import ugettext as _
-
-from modoboa.extensions.admin.forms import (
- ExportIdentitiesForm, ExportDomainsForm
-)
-from modoboa.extensions.admin.lib import get_domains, get_identities
-
-
-def _export(content, filename):
- """Export a csv file's content
-
- :param content: the content to export (string)
- :param filename: the name that will appear into the response
- :return: an ``HttpResponse`` object
- """
- resp = HttpResponse(content)
- resp["Content-Type"] = "text/csv"
- resp["Content-Length"] = len(content)
- resp["Content-Disposition"] = build_header(filename)
- return resp
-
-
-@login_required
-@user_passes_test(
- lambda u: u.has_perm("core.add_user") or u.has_perm("admin.add_alias")
-)
-def export_identities(request):
- ctx = {
- "title": _("Export identities"),
- "action_label": _("Export"),
- "action_classes": "submit",
- "formid": "exportform",
- "action": reverse("admin:identity_export"),
- }
-
- if request.method == "POST":
- form = ExportIdentitiesForm(request.POST)
- form.is_valid()
- fp = cStringIO.StringIO()
- csvwriter = csv.writer(fp, delimiter=form.cleaned_data["sepchar"])
- identities = get_identities(
- request.user, **request.session['identities_filters'])
- for ident in identities:
- ident.to_csv(csvwriter)
- content = fp.getvalue()
- fp.close()
- return _export(content, form.cleaned_data["filename"])
-
- ctx["form"] = ExportIdentitiesForm()
- return render(request, "common/generic_modal_form.html", ctx)
-
-
-@login_required
-@permission_required("admin.add_domain")
-def export_domains(request):
- ctx = {
- "title": _("Export domains"),
- "action_label": _("Export"),
- "action_classes": "submit",
- "formid": "exportform",
- "action": reverse("admin:domain_export"),
- }
-
- if request.method == "POST":
- form = ExportDomainsForm(request.POST)
- form.is_valid()
- fp = cStringIO.StringIO()
- csvwriter = csv.writer(fp, delimiter=form.cleaned_data["sepchar"])
- for dom in get_domains(request.user,
- **request.session['domains_filters']):
- dom.to_csv(csvwriter)
- content = fp.getvalue()
- fp.close()
- return _export(content, form.cleaned_data["filename"])
-
- ctx["form"] = ExportDomainsForm()
- return render(request, "common/generic_modal_form.html", ctx)
diff --git a/modoboa/extensions/admin/views/identity.py b/modoboa/extensions/admin/views/identity.py
deleted file mode 100644
index cf7898114..000000000
--- a/modoboa/extensions/admin/views/identity.py
+++ /dev/null
@@ -1,211 +0,0 @@
-"""Identity related views."""
-
-from django.contrib.auth.decorators import (
- login_required, permission_required, user_passes_test
-)
-from django.shortcuts import render
-from django.utils.translation import ugettext as _, ungettext
-from django.views.decorators.csrf import ensure_csrf_cookie
-
-import reversion
-
-from modoboa.core.models import User
-from modoboa.extensions.admin.forms import (
- AccountForm
-)
-from modoboa.extensions.admin.lib import get_identities
-from modoboa.extensions.admin.models import Mailbox, Domain
-from modoboa.lib import parameters, events
-from modoboa.lib.exceptions import (
- PermDeniedException, BadRequest
-)
-from modoboa.lib.listing import (
- get_sort_order, get_listing_page
-)
-from modoboa.lib.web_utils import (
- _render_to_string, render_to_json_response
-)
-
-
-@login_required
-@user_passes_test(
- lambda u: u.has_perm("core.add_user") or u.has_perm("admin.add_alias")
-)
-def _identities(request):
- filters = dict((fname, request.GET.get(fname, None))
- for fname in ['searchquery', 'idtfilter', 'grpfilter'])
- request.session['identities_filters'] = filters
- idents_list = get_identities(request.user, **filters)
- sort_order, sort_dir = get_sort_order(request.GET, "identity",
- ["identity", "name_or_rcpt", "tags"])
- if sort_order in ["identity", "name_or_rcpt"]:
- objects = sorted(idents_list, key=lambda o: getattr(o, sort_order),
- reverse=sort_dir == '-')
- else:
- objects = sorted(idents_list, key=lambda o: o.tags[0],
- reverse=sort_dir == '-')
- context = {
- "handle_mailboxes": parameters.get_admin(
- "HANDLE_MAILBOXES", raise_error=False)
- }
- page = get_listing_page(objects, request.GET.get("page", 1))
- if page is None:
- context["length"] = 0
- else:
- context["headers"] = _render_to_string(
- request, "admin/identity_headers.html", {})
- context["rows"] = _render_to_string(
- request, "admin/identities_table.html", {
- "identities": page.object_list
- }
- )
- context["pages"] = [page.number]
- return render_to_json_response(context)
-
-
-@login_required
-@permission_required("admin.add_mailbox")
-def list_quotas(request):
- from modoboa.lib.db_utils import db_type
-
- sort_order, sort_dir = get_sort_order(request.GET, "address")
- mboxes = Mailbox.objects.get_for_admin(
- request.user, request.GET.get("searchquery", None)
- )
- mboxes = mboxes.exclude(quota=0)
- if sort_order in ["address", "quota"]:
- mboxes = mboxes.order_by("%s%s" % (sort_dir, sort_order))
- elif sort_order == "quota_value__bytes":
- where = "admin_mailbox.address||'@'||admin_domain.name"
- mboxes = mboxes.extra(
- select={"quota_value__bytes": "admin_quota.bytes"},
- where=["admin_quota.username=%s" % where],
- tables=["admin_quota", "admin_domain"],
- order_by=["%s%s" % (sort_dir, sort_order)]
- )
- elif sort_order == "quota_usage":
- where = "admin_mailbox.address||'@'||admin_domain.name"
- db_type = db_type()
- if db_type == "postgres":
- select = (
- "(admin_quota.bytes::float / (CAST(admin_mailbox.quota "
- "AS BIGINT) * 1048576)) * 100"
- )
- else:
- select = (
- "admin_quota.bytes / (admin_mailbox.quota "
- "* 1048576) * 100"
- )
- if db_type == "mysql":
- where = "CONCAT(admin_mailbox.address,'@',admin_domain.name)"
- mboxes = mboxes.extra(
- select={'quota_usage': select},
- where=["admin_quota.username=%s" % where],
- tables=["admin_quota", "admin_domain"],
- order_by=["%s%s" % (sort_dir, sort_order)]
- )
- else:
- raise BadRequest(_("Invalid request"))
- page = get_listing_page(mboxes, request.GET.get("page", 1))
- context = {
- "headers": _render_to_string(
- request, "admin/quota_headers.html", {}
- )
- }
- if page is None:
- context["length"] = 0
- else:
- context["rows"] = _render_to_string(
- request, "admin/quotas.html", {
- "mboxes": page
- }
- )
- context["pages"] = [page.number]
- return render_to_json_response(context)
-
-
-@login_required
-@user_passes_test(
- lambda u: u.has_perm("admin.add_user") or u.has_perm("admin.add_alias")
- or u.has_perm("admin.add_mailbox")
-)
-def get_next_page(request):
- """Return the next page of the identity list."""
- if request.GET.get("objtype", "identity") == "identity":
- return _identities(request)
- return list_quotas(request)
-
-
-@login_required
-@user_passes_test(
- lambda u: u.has_perm("admin.add_user") or u.has_perm("admin.add_alias")
-)
-@ensure_csrf_cookie
-def identities(request, tplname="admin/identities.html"):
- return render(request, tplname, {
- "selection": "identities",
- "deflocation": "list/"
- })
-
-
-@login_required
-@permission_required("core.add_user")
-def accounts_list(request):
- accs = User.objects.filter(is_superuser=False) \
- .exclude(groups__name='SimpleUsers')
- res = [a.username for a in accs.all()]
- return render_to_json_response(res)
-
-
-@login_required
-@permission_required("core.add_user")
-@reversion.create_revision()
-def newaccount(request):
- """Create a new account."""
- from modoboa.extensions.admin.forms import AccountWizard
- return AccountWizard(request).process()
-
-
-@login_required
-@permission_required("core.change_user")
-@reversion.create_revision()
-def editaccount(request, accountid, tplname="common/tabforms.html"):
- account = User.objects.get(pk=accountid)
- if not request.user.can_access(account):
- raise PermDeniedException
- mb = None
- if account.mailbox_set.count():
- mb = account.mailbox_set.all()[0]
-
- instances = dict(general=account, mail=mb, perms=account)
- events.raiseEvent("FillAccountInstances", request.user, account, instances)
- return AccountForm(request, instances=instances).process()
-
-
-@login_required
-@permission_required("core.delete_user")
-def delaccount(request, accountid):
- keepdir = True if request.POST.get("keepdir", "false") == "true" else False
- User.objects.get(pk=accountid).delete(request.user, keep_mb_dir=keepdir)
- return render_to_json_response(
- ungettext("Account deleted", "Accounts deleted", 1)
- )
-
-
-@login_required
-@permission_required("admin.add_domain")
-def remove_permission(request):
- domid = request.GET.get("domid", None)
- daid = request.GET.get("daid", None)
- if domid is None or daid is None:
- raise BadRequest(_("Invalid request"))
- try:
- account = User.objects.get(pk=daid)
- domain = Domain.objects.get(pk=domid)
- except (User.DoesNotExist, Domain.DoesNotExist):
- raise BadRequest(_("Invalid request"))
- if not request.user.can_access(account) or \
- not request.user.can_access(domain):
- raise PermDeniedException
- domain.remove_admin(account)
- return render_to_json_response({})
diff --git a/modoboa/extensions/admin/views/import.py b/modoboa/extensions/admin/views/import.py
deleted file mode 100644
index 015db07d2..000000000
--- a/modoboa/extensions/admin/views/import.py
+++ /dev/null
@@ -1,177 +0,0 @@
-"""Import related views."""
-
-import csv
-
-from django.contrib.auth.decorators import (
- login_required, permission_required, user_passes_test
-)
-from django.core.urlresolvers import reverse
-from django.shortcuts import render
-from django.utils.translation import ugettext as _
-
-import reversion
-
-from modoboa.core.models import User
-from modoboa.extensions.admin.forms import ImportIdentitiesForm, ImportDataForm
-from modoboa.extensions.admin.models import (
- Domain, DomainAlias, Alias
-)
-from modoboa.lib import events
-from modoboa.lib.exceptions import ModoboaException, Conflict
-
-
-def import_domain(user, row, formopts):
- """Specific code for domains import"""
- dom = Domain()
- dom.from_csv(user, row)
-
-
-def import_domainalias(user, row, formopts):
- """Specific code for domain aliases import"""
- domalias = DomainAlias()
- domalias.from_csv(user, row)
-
-
-@login_required
-@permission_required("admin.add_domain")
-def import_domains(request):
- if request.method == "POST":
- return importdata(request)
-
- helptext = _("""Provide a CSV file where lines respect one of the following formats:
-
- domain; name; quota; enabled
- domainalias; name; targeted domain; enabled
- %s
-
-The first element of each line is mandatory and must be equal to one of the previous values.
-You can use a different character as separator.
-""" % ''.join([unicode(hlp) for hlp in
- events.raiseQueryEvent('ExtraDomainImportHelp')]))
-
- ctx = dict(
- title=_("Import domains"),
- action_label=_("Import"),
- action_classes="submit",
- action=reverse("admin:domain_import"),
- formid="importform",
- enctype="multipart/form-data",
- target="import_target",
- helptext=helptext,
- form=ImportDataForm()
- )
- return render(request, "admin/importform.html", ctx)
-
-
-def import_account(user, row, formopts):
- """Specific code for accounts import"""
- account = User()
- account.from_csv(user, row, formopts["crypt_password"])
-
-
-def _import_alias(user, row, **kwargs):
- """Specific code for aliases import"""
- alias = Alias()
- alias.from_csv(user, row, **kwargs)
-
-
-def import_alias(user, row, formopts):
- _import_alias(user, row, expected_elements=4)
-
-
-def import_forward(user, row, formopts):
- _import_alias(user, row, expected_elements=4)
-
-
-def import_dlist(user, row, formopts):
- _import_alias(user, row)
-
-
-@reversion.create_revision()
-def importdata(request, formclass=ImportDataForm):
- """Generic import function
-
- As the process of importing data from a CSV file is the same
- whatever the type, we do a maximum of the work here.
-
- :param request: a ``Request`` instance
- :param typ: a string indicating the object type being imported
- :return: a ``Response`` instance
- """
- error = None
- form = formclass(request.POST, request.FILES)
- if form.is_valid():
- try:
- reader = csv.reader(request.FILES['sourcefile'],
- delimiter=form.cleaned_data['sepchar'])
- except csv.Error as inst:
- error = str(inst)
-
- if error is None:
- try:
- cpt = 0
- for row in reader:
- if not row:
- continue
- try:
- fct = globals()["import_%s" % row[0].strip()]
- except KeyError:
- fct = events.raiseQueryEvent(
- 'ImportObject', row[0].strip()
- )
- if not fct:
- continue
- fct = fct[0]
- try:
- fct(request.user, row, form.cleaned_data)
- except Conflict:
- if form.cleaned_data["continue_if_exists"]:
- continue
- raise Conflict(
- _("Object already exists: %s"
- % form.cleaned_data['sepchar'].join(row[:2]))
- )
- cpt += 1
- msg = _("%d objects imported successfully" % cpt)
- return render(request, "admin/import_done.html", {
- "status": "ok", "msg": msg
- })
- except (ModoboaException) as e:
- error = str(e)
-
- return render(request, "admin/import_done.html", {
- "status": "ko", "msg": error
- })
-
-
-@login_required
-@user_passes_test(
- lambda u: u.has_perm("core.add_user") or u.has_perm("admin.add_alias")
-)
-def import_identities(request):
- if request.method == "POST":
- return importdata(request, ImportIdentitiesForm)
-
- helptext = _("""Provide a CSV file where lines respect one of the following formats:
-
-account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...]
-alias; address; enabled; internal recipient
-forward; address; enabled; external recipient
-dlist; address; enabled; recipient; recipient; ...
-
-The first element of each line is mandatory and must be equal to one of the previous values.
-
-You can use a different character as separator.
-""")
- ctx = dict(
- title=_("Import identities"),
- action_label=_("Import"),
- action_classes="submit",
- action=reverse("admin:identity_import"),
- formid="importform",
- enctype="multipart/form-data",
- target="import_target",
- form=ImportIdentitiesForm(),
- helptext=helptext
- )
- return render(request, "admin/importform.html", ctx)
diff --git a/modoboa/extensions/admin/views/user.py b/modoboa/extensions/admin/views/user.py
deleted file mode 100644
index 55166166c..000000000
--- a/modoboa/extensions/admin/views/user.py
+++ /dev/null
@@ -1,57 +0,0 @@
-import reversion
-from django.contrib.auth.decorators import login_required
-from django.utils.translation import ugettext as _
-from modoboa.lib.web_utils import (
- render_to_json_response, _render_to_string
-)
-from modoboa.extensions.admin.lib import needs_mailbox
-from modoboa.extensions.admin.models import Alias, Mailbox
-from modoboa.extensions.admin.forms import ForwardForm
-
-
-@login_required
-@needs_mailbox()
-@reversion.create_revision()
-def forward(request, tplname='admin/forward.html'):
- mb = request.user.mailbox_set.all()[0]
- try:
- al = Alias.objects.get(address=mb.address,
- domain__name=mb.domain.name)
- except Alias.DoesNotExist:
- al = None
- if request.method == "POST":
- form = ForwardForm(request.POST)
- error = None
- if form.is_valid():
- if al is None:
- al = Alias()
- al.address = mb.address
- al.domain = mb.domain
- al.enabled = mb.user.is_active
- intdests = []
- if form.cleaned_data["keepcopies"]:
- intdests += [mb]
- form.parse_dest()
- al.save(
- int_rcpts=intdests, ext_rcpts=form.dests, creator=request.user
- )
- return render_to_json_response(_("Forward updated"))
-
- return render_to_json_response(
- {'form_errors': form.errors}, status=400
- )
-
- form = ForwardForm()
- if al is not None:
- form.fields["dest"].initial = al.extmboxes
- try:
- al.mboxes.get(pk=mb.id)
- except Mailbox.DoesNotExist:
- pass
- else:
- form.fields["keepcopies"].initial = True
- return render_to_json_response({
- "content": _render_to_string(request, tplname, {
- "form": form
- })
- })
diff --git a/modoboa/lib/web_utils.py b/modoboa/lib/web_utils.py
index 947c32503..f79484023 100644
--- a/modoboa/lib/web_utils.py
+++ b/modoboa/lib/web_utils.py
@@ -162,7 +162,8 @@ def topredirection(request):
else:
path = reverse("core:user_index")
else:
- path = reverse("admin:domain_list")
+ # FIXME
+ path = reverse("modoboa_admin:domain_list")
return HttpResponseRedirect(path)
From fe8030ac87d4d2de2d830c37a20054162d5ebbef Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Feb 2015 09:54:58 +0100
Subject: [PATCH 02/25] Remove amavis extension.
---
modoboa/extensions/amavis/__init__.py | 0
modoboa/extensions/amavis/app_settings.py | 162 ------
modoboa/extensions/amavis/dbrouter.py | 30 --
modoboa/extensions/amavis/fixtures/demo.json | 1 -
modoboa/extensions/amavis/forms.py | 97 ----
.../extensions/amavis/general_callbacks.py | 211 --------
modoboa/extensions/amavis/lib.py | 345 ------------
.../extensions/amavis/management/__init__.py | 0
.../amavis/management/commands/__init__.py | 0
.../amavis/management/commands/amnotify.py | 94 ----
.../amavis/management/commands/qcleanup.py | 68 ---
.../amavis/migrations/0001_initial.py | 187 -------
.../extensions/amavis/migrations/__init__.py | 0
modoboa/extensions/amavis/models.py | 236 ---------
modoboa/extensions/amavis/modo_extension.py | 52 --
modoboa/extensions/amavis/sql_connector.py | 312 -----------
modoboa/extensions/amavis/sql_email.py | 52 --
.../amavis/static/amavis/css/quarantine.css | 90 ----
.../amavis/static/amavis/css/selfservice.css | 21 -
.../amavis/static/amavis/js/quarantine.js | 489 ------------------
.../amavis/static/amavis/js/selfservice.js | 30 --
.../amavis/domain_content_filter.html | 18 -
.../amavis/templates/amavis/email_list.html | 31 --
.../amavis/templates/amavis/emails_page.html | 34 --
.../templates/amavis/getmailcontent.html | 1 -
.../amavis/templates/amavis/index.html | 37 --
.../amavis/templates/amavis/mailheaders.html | 5 -
.../templates/amavis/main_action_bar.html | 79 ---
.../notifications/pending_requests.html | 14 -
.../amavis/templates/amavis/viewheader.html | 4 -
.../amavis/viewmail_selfservice.html | 28 -
.../amavis/templatetags/__init__.py | 0
.../amavis/templatetags/amavis_tags.py | 132 -----
modoboa/extensions/amavis/urls.py | 24 -
modoboa/extensions/amavis/views.py | 436 ----------------
35 files changed, 3320 deletions(-)
delete mode 100644 modoboa/extensions/amavis/__init__.py
delete mode 100644 modoboa/extensions/amavis/app_settings.py
delete mode 100644 modoboa/extensions/amavis/dbrouter.py
delete mode 100644 modoboa/extensions/amavis/fixtures/demo.json
delete mode 100644 modoboa/extensions/amavis/forms.py
delete mode 100644 modoboa/extensions/amavis/general_callbacks.py
delete mode 100644 modoboa/extensions/amavis/lib.py
delete mode 100644 modoboa/extensions/amavis/management/__init__.py
delete mode 100644 modoboa/extensions/amavis/management/commands/__init__.py
delete mode 100644 modoboa/extensions/amavis/management/commands/amnotify.py
delete mode 100644 modoboa/extensions/amavis/management/commands/qcleanup.py
delete mode 100644 modoboa/extensions/amavis/migrations/0001_initial.py
delete mode 100644 modoboa/extensions/amavis/migrations/__init__.py
delete mode 100644 modoboa/extensions/amavis/models.py
delete mode 100644 modoboa/extensions/amavis/modo_extension.py
delete mode 100644 modoboa/extensions/amavis/sql_connector.py
delete mode 100644 modoboa/extensions/amavis/sql_email.py
delete mode 100644 modoboa/extensions/amavis/static/amavis/css/quarantine.css
delete mode 100644 modoboa/extensions/amavis/static/amavis/css/selfservice.css
delete mode 100644 modoboa/extensions/amavis/static/amavis/js/quarantine.js
delete mode 100644 modoboa/extensions/amavis/static/amavis/js/selfservice.js
delete mode 100644 modoboa/extensions/amavis/templates/amavis/domain_content_filter.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/email_list.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/emails_page.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/getmailcontent.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/index.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/mailheaders.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/main_action_bar.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/notifications/pending_requests.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/viewheader.html
delete mode 100644 modoboa/extensions/amavis/templates/amavis/viewmail_selfservice.html
delete mode 100644 modoboa/extensions/amavis/templatetags/__init__.py
delete mode 100644 modoboa/extensions/amavis/templatetags/amavis_tags.py
delete mode 100644 modoboa/extensions/amavis/urls.py
delete mode 100644 modoboa/extensions/amavis/views.py
diff --git a/modoboa/extensions/amavis/__init__.py b/modoboa/extensions/amavis/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/amavis/app_settings.py b/modoboa/extensions/amavis/app_settings.py
deleted file mode 100644
index 572d31d99..000000000
--- a/modoboa/extensions/amavis/app_settings.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# coding: utf-8
-
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-
-from modoboa.lib.form_utils import SeparatorField, YesNoField, InlineRadioSelect
-from modoboa.lib.parameters import AdminParametersForm, UserParametersForm
-
-
-class ParametersForm(AdminParametersForm):
-
- """Extension settings."""
-
- app = "amavis"
-
- qsettings_sep = SeparatorField(label=_("Quarantine settings"))
-
- max_messages_age = forms.IntegerField(
- label=_("Maximum message age"),
- initial=14,
- help_text=_(
- "Quarantine messages maximum age (in days) before deletion"
- )
- )
-
- sep1 = SeparatorField(label=_("Messages releasing"))
-
- released_msgs_cleanup = YesNoField(
- label=_("Remove released messages"),
- initial="no",
- help_text=_("Remove messages marked as released while cleaning up "
- "the database")
- )
-
- am_pdp_mode = forms.ChoiceField(
- label=_("Amavis connection mode"),
- choices=[("inet", "inet"), ("unix", "unix")],
- initial="unix",
- help_text=_("Mode used to access the PDP server"),
- widget=InlineRadioSelect(attrs={"type": "checkbox"})
- )
-
- am_pdp_host = forms.CharField(
- label=_("PDP server address"),
- initial="localhost",
- help_text=_("PDP server address (if inet mode)"),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- am_pdp_port = forms.IntegerField(
- label=_("PDP server port"),
- initial=9998,
- help_text=_("PDP server port (if inet mode)")
- )
-
- am_pdp_socket = forms.CharField(
- label=_("PDP server socket"),
- initial="/var/amavis/amavisd.sock",
- help_text=_("Path to the PDP server socket (if unix mode)")
- )
-
- user_can_release = YesNoField(
- label=_("Allow direct release"),
- initial="no",
- help_text=_("Allow users to directly release their messages")
- )
-
- self_service = YesNoField(
- label=_("Enable self-service mode"),
- initial="no",
- help_text=_("Activate the 'self-service' mode")
- )
-
- notifications_sender = forms.EmailField(
- label=_("Notifications sender"),
- initial="notification@modoboa.org",
- help_text=_("The e-mail address used to send notitications")
- )
-
- lsep = SeparatorField(label=_("Manual learning"))
-
- manual_learning = YesNoField(
- label=_("Enable manual learning"),
- initial="yes",
- help_text=_(
- "Allow super administrators to manually train Spamassassin"
- )
- )
-
- sa_is_local = YesNoField(
- label=_("Is Spamassassin local?"),
- initial="yes",
- help_text=_(
- "Tell if Spamassassin is running on the same server than modoboa"
- )
- )
-
- default_user = forms.CharField(
- label=_("Default user"),
- initial="amavis",
- help_text=_(
- "Name of the user owning the default bayesian database"
- )
- )
-
- spamd_address = forms.CharField(
- label=_("Spamd address"),
- initial="127.0.0.1",
- help_text=_("The IP address where spamd can be reached")
- )
-
- spamd_port = forms.IntegerField(
- label=_("Spamd port"),
- initial=783,
- help_text=_("The TCP port spamd is listening on")
- )
-
- domain_level_learning = YesNoField(
- label=_("Enable per-domain manual learning"),
- initial="no",
- help_text=_(
- "Allow domain administrators to train Spamassassin "
- "(within dedicated per-domain databases)"
- )
- )
-
- user_level_learning = YesNoField(
- label=_("Enable per-user manual learning"),
- initial="no",
- help_text=_(
- "Allow simple users to personally train Spamassassin "
- "(within a dedicated database)"
- )
- )
-
- visibility_rules = {
- "am_pdp_host": "am_pdp_mode=inet",
- "am_pdp_port": "am_pdp_mode=inet",
- "am_pdp_socket": "am_pdp_mode=unix",
-
- "sa_is_local": "manual_learning=yes",
- "default_user": "manual_learning=yes",
- "spamd_address": "sa_is_local=no",
- "spamd_port": "sa_is_local=no",
- "domain_level_learning": "manual_learning=yes",
- "user_level_learning": "manual_learning=yes"
- }
-
-
-class UserSettings(UserParametersForm):
-
- """Per-user settings."""
-
- app = "amavis"
-
- dsep = SeparatorField(label=_("Display"))
-
- messages_per_page = forms.IntegerField(
- initial=40,
- label=_("Number of displayed emails per page"),
- help_text=_("Set the maximum number of messages displayed in a page")
- )
diff --git a/modoboa/extensions/amavis/dbrouter.py b/modoboa/extensions/amavis/dbrouter.py
deleted file mode 100644
index af582ef80..000000000
--- a/modoboa/extensions/amavis/dbrouter.py
+++ /dev/null
@@ -1,30 +0,0 @@
-class AmavisRouter(object):
- """A router to control all database operations on models in
- the amavis application"""
-
- def db_for_read(self, model, **hints):
- "Point all operations on amavis models to 'amavis'"
- if model._meta.app_label == 'amavis':
- return 'amavis'
- return None
-
- def db_for_write(self, model, **hints):
- "Point all operations on amavis models to 'amavis'"
- if model._meta.app_label == 'amavis':
- return 'amavis'
- return None
-
- def allow_relation(self, obj1, obj2, **hints):
- "Allow any relation if a model in amavis is involved"
- if obj1._meta.app_label == 'amavis' \
- or obj2._meta.app_label == 'amavis':
- return True
- return None
-
- def allow_syncdb(self, db, model):
- "Make sure the amavis app only appears on the 'amavis' db"
- if db == 'amavis':
- return model._meta.app_label == 'amavis'
- elif model._meta.app_label == 'amavis':
- return False
- return None
diff --git a/modoboa/extensions/amavis/fixtures/demo.json b/modoboa/extensions/amavis/fixtures/demo.json
deleted file mode 100644
index 5075ab854..000000000
--- a/modoboa/extensions/amavis/fixtures/demo.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"pk": 1, "model": "amavis.users", "fields": {"priority": 7, "policy": 1, "email": "@demo.local", "fullname": "demo.local"}}]
\ No newline at end of file
diff --git a/modoboa/extensions/amavis/forms.py b/modoboa/extensions/amavis/forms.py
deleted file mode 100644
index 7af8c2b52..000000000
--- a/modoboa/extensions/amavis/forms.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# coding: utf-8
-"""
-Amavis forms.
-"""
-
-from django import forms
-from django.utils.translation import ugettext as _
-
-from modoboa.lib import parameters
-from modoboa.lib.form_utils import InlineRadioSelect
-from .models import Policy, Users
-
-
-class DomainPolicyForm(forms.ModelForm):
-
- spam_subject_tag2_act = forms.BooleanField()
-
- class Meta:
- model = Policy
- fields = ('bypass_virus_checks', 'bypass_spam_checks',
- 'spam_tag2_level', 'spam_subject_tag2',
- 'spam_kill_level', 'bypass_banned_checks')
- widgets = {
- 'bypass_virus_checks': InlineRadioSelect(),
- 'bypass_spam_checks': InlineRadioSelect(),
- 'spam_tag2_level': forms.TextInput(
- attrs={'class': 'form-control'}),
- 'spam_kill_level': forms.TextInput(
- attrs={'class': 'form-control'}),
- 'spam_subject_tag2': forms.TextInput(
- attrs={'class': 'form-control'}),
- 'bypass_banned_checks': InlineRadioSelect(),
- }
-
- def __init__(self, *args, **kwargs):
- if "instance" in kwargs:
- self.domain = kwargs["instance"]
- try:
- policy = Users.objects.get(
- email="@%s" % self.domain.name).policy
- kwargs["instance"] = policy
- except (Users.DoesNotExist, Policy.DoesNotExist):
- del kwargs["instance"]
- super(DomainPolicyForm, self).__init__(*args, **kwargs)
- for field in self.fields.keys():
- self.fields[field].required = False
-
- def save(self, user, commit=True):
- policy = super(DomainPolicyForm, self).save(commit=False)
- for field in ['bypass_spam_checks', 'bypass_virus_checks',
- 'bypass_banned_checks']:
- if getattr(policy, field) == '':
- setattr(policy, field, None)
-
- if self.cleaned_data['spam_subject_tag2_act']:
- policy.spam_subject_tag2 = None
-
- if commit:
- policy.save()
- try:
- u = Users.objects.get(fullname=policy.policy_name)
- except Users.DoesNotExist:
- u = Users.objects.get(email="@%s" % self.domain.name)
- u.policy = policy
- policy.save()
- return policy
-
-
-class LearningRecipientForm(forms.Form):
-
- """A form to select the recipient of a learning request."""
-
- recipient = forms.ChoiceField(
- label=None, choices=[]
- )
- ltype = forms.ChoiceField(
- label="", choices=[("spam", "spam"), ("ham", "ham")],
- widget=forms.widgets.HiddenInput
- )
- selection = forms.CharField(
- label="", widget=forms.widgets.HiddenInput)
-
- def __init__(self, user, *args, **kwargs):
- """Constructor."""
- super(LearningRecipientForm, self).__init__(*args, **kwargs)
- choices = []
- if user.group == "SuperAdmins":
- choices.append(("global", _("Global database")))
- domain_level_learning = parameters.get_admin(
- "DOMAIN_LEVEL_LEARNING") == "yes"
- user_level_learning = parameters.get_admin(
- "USER_LEVEL_LEARNING") == "yes"
- if domain_level_learning:
- choices.append(("domain", _("Domain's database")))
- if user_level_learning:
- choices.append(("user", _("User's database")))
- self.fields["recipient"].choices = choices
diff --git a/modoboa/extensions/amavis/general_callbacks.py b/modoboa/extensions/amavis/general_callbacks.py
deleted file mode 100644
index 87bfd3115..000000000
--- a/modoboa/extensions/amavis/general_callbacks.py
+++ /dev/null
@@ -1,211 +0,0 @@
-"""General event callbacks."""
-
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext as _
-from django.template import Template, Context
-
-from modoboa.lib import events, parameters
-from modoboa.extensions.admin.models import DomainAlias
-from modoboa.extensions.amavis.lib import (
- create_user_and_policy, update_user_and_policy, delete_user_and_policy,
- create_user_and_use_policy, delete_user
-)
-from .lib import manual_learning_enabled
-from .models import Policy, Users
-
-
-def create_relay_domains_records():
- """Create records for existing relay domains."""
- from modoboa.extensions.postfix_relay_domains.models import RelayDomain
-
- for rdom in RelayDomain.objects.all():
- policy = create_user_and_policy("@{0}".format(rdom.name))
- for rdomalias in rdom.relaydomainalias_set.all():
- rdomalias_pattern = "@{0}".format(rdomalias.name)
- create_user_and_use_policy(rdomalias_pattern, policy)
-
-
-@events.observe("InitialDataLoaded")
-def load_relay_domains_dependant_data(name):
- """Load relay domains dependant data."""
- if name != "postfix_relay_domains":
- return
- create_relay_domains_records()
-
-
-@events.observe("UserMenuDisplay")
-def menu(target, user):
- if target == "top_menu":
- return [
- {"name": "quarantine",
- "label": _("Quarantine"),
- "url": reverse('amavis:index')}
- ]
- return []
-
-
-@events.observe("DomainCreated")
-def on_domain_created(user, domain):
- create_user_and_policy("@{0}".format(domain.name))
-
-
-@events.observe("DomainModified")
-def on_domain_modified(domain):
- update_user_and_policy(
- "@{0}".format(domain.oldname),
- "@{0}".format(domain.name)
- )
-
-
-@events.observe("DomainDeleted")
-def on_domain_deleted(domain):
- delete_user_and_policy("@{0}".format(domain.name))
-
-
-@events.observe("DomainAliasCreated")
-def on_domain_alias_created(user, domainalias):
- create_user_and_use_policy(
- "@{0}".format(domainalias.name),
- "@{0}".format(domainalias.target.name)
- )
-
-
-@events.observe("DomainAliasDeleted")
-def on_domain_alias_deleted(domainaliases):
- if isinstance(domainaliases, DomainAlias):
- domainaliases = [domainaliases]
- for domainalias in domainaliases:
- delete_user("@{0}".format(domainalias.name))
-
-
-@events.observe("MailboxModified")
-def on_mailbox_modified(mailbox):
- """Update amavis records if address has changed."""
- if parameters.get_admin("MANUAL_LEARNING") == "no" or \
- not hasattr(mailbox, "old_full_address") or \
- mailbox.full_address == mailbox.old_full_address:
- return
- user = Users.objects.select_related.get(email=mailbox.old_full_address)
- full_address = mailbox.full_address
- user.email = full_address
- user.policy.policy_name = full_address[:32]
- user.policy.sa_username = full_address
- user.policy.save()
- user.save()
-
-
-@events.observe("MailboxDeleted")
-def on_mailbox_deleted(mailbox):
- """Clean amavis database when a mailbox is removed."""
- if parameters.get_admin("MANUAL_LEARNING") == "no":
- return
- delete_user_and_policy("@{0}".format(mailbox.full_address))
-
-
-@events.observe("MailboxAliasCreated")
-def on_mailboxalias_created(user, alias):
- """Create amavis record for the new alias.
-
- FIXME: how to deal with distibution lists ?
- """
- if not manual_learning_enabled(user) or alias.type != "alias":
- return
- try:
- policy = Policy.objects.get(
- policy_name=alias.mboxes.all()[0].full_address
- )
- except Policy.DoesNotExist:
- return
- else:
- email = alias.full_address
- Users.objects.create(
- email=email, policy=policy, fullname=email, priority=7
- )
-
-
-@events.observe("MailboxAliasDeleted")
-def on_mailboxalias_deleted(alias):
- """Clean amavis database when an alias is removed."""
- if parameters.get_admin("MANUAL_LEARNING") == "no":
- return
- if Users.objects.filter(email=alias.full_address).exists():
- Users.objects.delete(email=alias.full_address)
-
-
-@events.observe("GetStaticContent")
-def extra_static_content(caller, st_type, user):
- if user.group == "SimpleUsers" or st_type != "js":
- return []
-
- if caller == 'domains':
- tpl = Template("""
-""")
-
- return [tpl.render(Context({}))]
- return []
-
-
-@events.observe("TopNotifications")
-def check_for_pending_requests(request, include_all):
- """
- Check if release requests are pending.
- """
- from .sql_connector import get_connector
-
- if parameters.get_admin("USER_CAN_RELEASE") == "yes" \
- or request.user.group == "SimpleUsers":
- return []
-
- nbrequests = get_connector(user=request.user).get_pending_requests()
- if not nbrequests:
- return [{"id": "nbrequests", "counter": 0}] if include_all \
- else []
-
- url = reverse("amavis:index")
- url += "#listing/?viewrequests=1"
- return [{
- "id": "nbrequests", "url": url, "text": _("Pending requests"),
- "counter": nbrequests, "level": "danger"
- }]
-
-
-def send_amavis_form():
- """
- """
- from .forms import DomainPolicyForm
- return [{
- 'id': 'amavis', 'title': _("Content filter"), 'cls': DomainPolicyForm,
- 'formtpl': 'amavis/domain_content_filter.html'
- }]
-
-
-@events.observe("ExtraDomainForm")
-def extra_domain_form(user, domain):
- if not user.has_perm("admin.view_domains"):
- return []
- return send_amavis_form()
-
-
-@events.observe('ExtraRelayDomainForm')
-def extra_relaydomain_form(user, rdomain):
- if not user.has_perm("postfix_relay_domains.add_relaydomain"):
- return []
- return send_amavis_form()
-
-
-@events.observe("FillDomainInstances")
-def fill_domain_instances(user, domain, instances):
- if not user.has_perm("admin.view_domains"):
- return
- instances["amavis"] = domain
-
-
-@events.observe("FillRelayDomainInstances")
-def fill_relaydomain_instances(user, rdomain, instances):
- if not user.has_perm("postfix_relay_domains.add_relaydomain"):
- return
- instances["amavis"] = rdomain
diff --git a/modoboa/extensions/amavis/lib.py b/modoboa/extensions/amavis/lib.py
deleted file mode 100644
index a1ab982e7..000000000
--- a/modoboa/extensions/amavis/lib.py
+++ /dev/null
@@ -1,345 +0,0 @@
-# coding: utf-8
-
-from functools import wraps
-import re
-import socket
-import string
-import struct
-
-from django.utils.translation import ugettext as _
-from django.core.urlresolvers import reverse
-
-from modoboa.extensions.admin.models import Mailbox, Alias
-from modoboa.lib import parameters
-from modoboa.lib.email_utils import split_mailbox
-from modoboa.lib.exceptions import InternalError
-from modoboa.lib.sysutils import exec_cmd
-from modoboa.lib.web_utils import NavigationParameters
-from .models import Users, Policy
-
-
-def selfservice(ssfunc=None):
- """Decorator used to expose views to the 'self-service' feature
-
- The 'self-service' feature allows users to act on quarantined
- messages without beeing authenticated.
-
- This decorator only acts as a 'router'.
-
- :param ssfunc: the function to call if the 'self-service'
- pre-requisites are satisfied
- """
- def decorator(f):
- @wraps(f)
- def wrapped_f(request, *args, **kwargs):
- if request.user.is_authenticated():
- return f(request, *args, **kwargs)
- if parameters.get_admin("SELF_SERVICE") == "no":
- from django.contrib.auth.views import redirect_to_login
- return redirect_to_login(
- reverse("amavis:index")
- )
- return ssfunc(request, *args, **kwargs)
- return wrapped_f
- return decorator
-
-
-class AMrelease(object):
- def __init__(self):
- mode = parameters.get_admin("AM_PDP_MODE")
- try:
- if mode == "inet":
- host = parameters.get_admin('AM_PDP_HOST')
- port = parameters.get_admin('AM_PDP_PORT')
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.connect((host, int(port)))
- else:
- path = parameters.get_admin('AM_PDP_SOCKET')
- self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- self.sock.connect(path)
- except socket.error, err:
- raise InternalError(
- _("Connection to amavis failed: %s" % str(err))
- )
-
- def decode(self, answer):
- def repl(match):
- return struct.pack("B", string.atoi(match.group(0)[1:], 16))
-
- return re.sub(r"%([0-9a-fA-F]{2})", repl, answer)
-
- def __del__(self):
- self.sock.close()
-
- def sendreq(self, mailid, secretid, recipient, *others):
- self.sock.send("""request=release
-mail_id=%s
-secret_id=%s
-quar_type=Q
-recipient=%s
-
-""" % (mailid, secretid, recipient))
- answer = self.sock.recv(1024)
- answer = self.decode(answer)
- if re.search(r"250 [\d\.]+ Ok", answer):
- return True
- return False
-
-
-class SpamassassinClient(object):
-
- """A stupid spamassassin client."""
-
- def __init__(self, user, recipient_db):
- """Constructor."""
- self._sa_is_local = parameters.get_admin("SA_IS_LOCAL")
- self._default_username = parameters.get_admin("DEFAULT_USER")
- self._recipient_db = recipient_db
- self._setup_cache = {}
- self._username_cache = []
- if user.group == "SimpleUsers":
- user_level_learning = parameters.get_admin("USER_LEVEL_LEARNING")
- if user_level_learning == "yes":
- self._username = user.email
- else:
- self._username = None
- self.error = None
- if self._sa_is_local == "yes":
- self._learn_cmd = "sa-learn --{0} --no-sync -u {1}"
- self._learn_cmd_kwargs = {}
- self._expected_exit_codes = [0]
- else:
- self._learn_cmd = "spamc -d {0} -p {1}".format(
- parameters.get_admin("SPAMD_ADDRESS"),
- parameters.get_admin("SPAMD_PORT")
- )
- self._learn_cmd += " -L {0} -u {1}"
- self._learn_cmd_kwargs = {}
- self._expected_exit_codes = [5, 6]
-
- def _get_mailbox_from_rcpt(self, rcpt):
- """Retrieve a mailbox from a recipient address."""
- local_part, domname = split_mailbox(rcpt)
- try:
- mailbox = Mailbox.objects.select_related("domain").get(
- address=local_part, domain__name=domname)
- except Mailbox.DoesNotExist:
- try:
- alias = Alias.objects.select_related("domain").get(
- address=local_part, domain__name=domname)
- except Alias.DoesNotExist:
- raise InternalError(_("No recipient found"))
- if alias.type != "alias":
- return None
- mailbox = alias.mboxes.all()[0]
- return mailbox
-
- def _learn(self, rcpt, msg, mtype):
- """Internal method to call the learning command."""
- if self._username is None:
- if self._recipient_db == "global":
- username = self._default_username
- else:
- mbox = self._get_mailbox_from_rcpt(rcpt)
- if mbox is None:
- username = self._default_username
- if self._recipient_db == "domain":
- username = mbox.domain.name
- if username not in self._setup_cache and \
- setup_manual_learning_for_domain(mbox.domain):
- self._setup_cache[username] = True
- else:
- username = mbox.full_address
- if username not in self._setup_cache and \
- setup_manual_learning_for_mbox(mbox):
- self._setup_cache[username] = True
- else:
- username = self._username
- if username not in self._username_cache:
- self._username_cache.append(username)
- cmd = self._learn_cmd.format(mtype, username)
- code, output = exec_cmd(cmd, pinput=msg, **self._learn_cmd_kwargs)
- if code in self._expected_exit_codes:
- return True
- self.error = output
- return False
-
- def learn_spam(self, rcpt, msg):
- """Learn new spam."""
- return self._learn(rcpt, msg, "spam")
-
- def learn_ham(self, rcpt, msg):
- """Learn new ham."""
- return self._learn(rcpt, msg, "ham")
-
- def done(self):
- """Call this method at the end of the processing."""
- if self._sa_is_local:
- for username in self._username_cache:
- exec_cmd("sa-learn -u {0} --sync".format(username),
- **self._learn_cmd_kwargs)
-
-
-class QuarantineNavigationParameters(NavigationParameters):
- """
- Specific NavigationParameters subclass for the quarantine.
- """
- def __init__(self, request):
- super(QuarantineNavigationParameters, self).__init__(
- request, 'quarantine_navparams'
- )
- self.parameters += [
- ('pattern', '', False),
- ('criteria', 'from_addr', False),
- ('msgtype', None, False),
- ('viewrequests', None, False)
- ]
-
- def _store_page(self):
- """Specific method to store the current page."""
- if self.request.GET.get("reset_page", None) or "page" not in self:
- self["page"] = 1
- else:
- page = self.request.GET.get("page", None)
- if page is not None:
- self["page"] = int(page)
-
- def back_to_listing(self):
- """Return the current listing URL.
-
- Looks into the user's session and the current request to build
- the URL.
-
- :return: a string
- """
- url = "listing"
- params = []
- navparams = self.request.session[self.sessionkey]
- if "page" in navparams:
- params += ["page=%s" % navparams["page"]]
- if "order" in navparams:
- params += ["sort_order=%s" % navparams["order"]]
- params += ["%s=%s" % (p[0], navparams[p[0]])
- for p in self.parameters if p[0] in navparams]
- if params:
- url += "?%s" % ("&".join(params))
- return url
-
-
-def create_user_and_policy(name, priority=7):
- """Create records.
-
- Create two records (a user and a policy) using :keyword:`name` as
- an identifier.
-
- :param str name: name
- :return: the new ``Policy`` object
- """
- if Users.objects.filter(email=name).exists():
- return Policy.objects.get(policy_name=name[:32])
- policy = Policy.objects.create(policy_name=name[:32])
- Users.objects.create(
- email=name, fullname=name, priority=priority, policy=policy
- )
- return policy
-
-
-def create_user_and_use_policy(name, policy, priority=7):
- """Create a *users* record and use an existing policy.
-
- :param str name: user record name
- :param str policy: string or Policy instance
- """
- if isinstance(policy, basestring):
- policy = Policy.objects.get(policy_name=policy[:32])
- Users.objects.get_or_create(
- email=name, fullname=name, priority=priority, policy=policy
- )
-
-
-def update_user_and_policy(oldname, newname):
- """Update records.
-
- :param str oldname: old name
- :param str newname: new name
- """
- if oldname == newname:
- return
- u = Users.objects.get(email=oldname)
- u.email = newname
- u.fullname = newname
- u.policy.policy_name = newname[:32]
- u.policy.save()
- u.save()
-
-
-def delete_user_and_policy(name):
- """Delete records.
-
- :param str name: identifier
- """
- try:
- u = Users.objects.get(email=name)
- except Users.DoesNotExist:
- return
- u.policy.delete()
- u.delete()
-
-
-def delete_user(name):
- """Delete a *users* record.
-
- :param str name: user record name
- """
- try:
- Users.objects.get(email=name).delete()
- except Users.DoesNotExist:
- pass
-
-
-def manual_learning_enabled(user):
- """Check if manual learning is enabled or not.
-
- Also check for :kw:`user` if necessary.
-
- :return: True if learning is enabled, False otherwise.
- """
- manual_learning = parameters.get_admin("MANUAL_LEARNING") == "yes"
- if manual_learning and user.group != 'SuperAdmins':
- domain_level_learning = parameters.get_admin(
- "DOMAIN_LEVEL_LEARNING") == "yes"
- user_level_learning = parameters.get_admin(
- "USER_LEVEL_LEARNING") == "yes"
- if user.has_perm("admin.view_domains"):
- manual_learning = domain_level_learning or user_level_learning
- else:
- manual_learning = user_level_learning
- return manual_learning
-
-
-def setup_manual_learning_for_domain(domain):
- """Setup manual learning if necessary.
-
- :return: True if learning has been setup, False otherwise
- """
- if Policy.objects.filter(sa_username=domain.name).exists():
- return False
- policy = Policy.objects.get(policy_name=domain.name[:32])
- policy.sa_username = domain.name
- policy.save()
- return True
-
-
-def setup_manual_learning_for_mbox(mbox):
- """Setup manual learning if necessary.
-
- :return: True if learning has been setup, False otherwise
- """
- result = False
- pname = mbox.full_address[:32]
- if not Policy.objects.filter(policy_name=pname).exists():
- policy = create_user_and_policy(pname)
- for alias in mbox.alias_addresses:
- create_user_and_use_policy(alias, policy)
- result = True
- return result
diff --git a/modoboa/extensions/amavis/management/__init__.py b/modoboa/extensions/amavis/management/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/amavis/management/commands/__init__.py b/modoboa/extensions/amavis/management/commands/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/amavis/management/commands/amnotify.py b/modoboa/extensions/amavis/management/commands/amnotify.py
deleted file mode 100644
index 209350da3..000000000
--- a/modoboa/extensions/amavis/management/commands/amnotify.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-from optparse import make_option
-
-from django.core.management.base import BaseCommand, CommandError
-from django.template.loader import render_to_string
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext as _
-
-from modoboa.core.management.commands import CloseConnectionMixin
-from modoboa.core.models import User
-from modoboa.lib import parameters
-from modoboa.lib.email_utils import sendmail_simple
-from modoboa.extensions.admin.models import Domain
-
-from modoboa.extensions.amavis.models import (
- Msgrcpt
-)
-from modoboa.extensions.amavis.sql_connector import get_connector
-
-
-class Command(BaseCommand, CloseConnectionMixin):
- help = 'Amavis notification tool'
-
- sender = None
- baseurl = None
- listingurl = None
-
- option_list = BaseCommand.option_list + (
- make_option("--baseurl", type="string", default=None,
- help="The scheme and hostname used to access Modoboa"),
- make_option("--smtp_host", type="string", default="localhost",
- help="The address of the SMTP server used to send notifications"),
- make_option("--smtp_port", type="int", default=25,
- help="The listening port of the SMTP server used to send notifications"),
- make_option("--verbose", action="store_true",
- help="Activate verbose mode")
- )
-
- def handle(self, *args, **options):
- if options["baseurl"] is None:
- raise CommandError("You must provide the --baseurl option")
- self.options = options
- self.notify_admins_pending_requests()
-
- def send_pr_notification(self, rcpt, reqs):
- if self.options["verbose"]:
- print "Sending notification to %s" % rcpt
- total = reqs.count()
- reqs = reqs.all()[:10]
- content = render_to_string(
- "amavis/notifications/pending_requests.html", dict(
- total=total, requests=reqs,
- baseurl=self.baseurl, listingurl=self.listingurl
- )
- )
- status, msg = sendmail_simple(
- self.sender, rcpt,
- subject=_("[modoboa] Pending release requests"),
- content=content,
- server=self.options["smtp_host"],
- port=self.options["smtp_port"]
- )
- if not status:
- print msg
-
- def notify_admins_pending_requests(self):
- self.sender = parameters.get_admin("NOTIFICATIONS_SENDER",
- app="amavis")
- self.baseurl = self.options["baseurl"].strip("/")
- self.listingurl = self.baseurl \
- + reverse("amavis:_mail_list") \
- + "?viewrequests=1"
-
- for da in User.objects.filter(groups__name="DomainAdmins"):
- if not da.mailbox_set.count():
- continue
- rcpt = da.mailbox_set.all()[0].full_address
- reqs = get_connector().get_domains_pending_requests(
- Domain.objects.get_for_admin(da)
- )
- if reqs.count():
- self.send_pr_notification(rcpt, reqs)
-
- reqs = Msgrcpt.objects.filter(rs='p')
- if not reqs.count():
- if self.options["verbose"]:
- print "No release request currently pending"
- return
- for su in User.objects.filter(is_superuser=True):
- if not su.mailbox_set.count():
- continue
- rcpt = su.mailbox_set.all()[0].full_address
- self.send_pr_notification(rcpt, reqs)
diff --git a/modoboa/extensions/amavis/management/commands/qcleanup.py b/modoboa/extensions/amavis/management/commands/qcleanup.py
deleted file mode 100644
index 47e2d6dce..000000000
--- a/modoboa/extensions/amavis/management/commands/qcleanup.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-
-import time
-from optparse import make_option
-
-from django.core.management.base import BaseCommand
-
-from modoboa.core.management.commands import CloseConnectionMixin
-from modoboa.extensions.amavis.models import (
- Msgrcpt, Msgs, Maddr
-)
-from modoboa.lib import parameters
-
-
-class Command(BaseCommand, CloseConnectionMixin):
- args = ''
- help = 'Amavis quarantine cleanup'
-
- option_list = BaseCommand.option_list + (
- make_option('--debug',
- action='store_true',
- default=False,
- help='Activate debug output'),
- make_option('--verbose',
- action='store_true',
- default=False,
- help='Display informational messages')
- )
-
- def __vprint(self, msg):
- if not self.verbose:
- return
- print msg
-
- def handle(self, *args, **options):
- if options["debug"]:
- import logging
- l = logging.getLogger("django.db.backends")
- l.setLevel(logging.DEBUG)
- l.addHandler(logging.StreamHandler())
- self.verbose = options["verbose"]
-
- max_messages_age = int(parameters.get_admin("MAX_MESSAGES_AGE",
- app="amavis"))
-
- flags = ['D']
- if parameters.get_admin("RELEASED_MSGS_CLEANUP",
- app="amavis") == "yes":
- flags += ['R']
-
- self.__vprint("Deleting marked messages...")
- ids = Msgrcpt.objects.filter(rs__in=flags).values("mail_id").distinct()
- for msg in Msgs.objects.filter(mail_id__in=ids):
- if not msg.msgrcpt_set.exclude(rs__in=flags).count():
- msg.delete()
-
- self.__vprint(
- "Deleting messages older than %d days..." % max_messages_age)
- limit = int(time.time()) - (max_messages_age * 24 * 3600)
- Msgs.objects.filter(time_num__lt=limit).delete()
-
- self.__vprint("Deleting unreferenced e-mail addresses...")
- for maddr in Maddr.objects.all():
- if not maddr.msgs_set.count() and not maddr.msgrcpt_set.count():
- maddr.delete()
-
- self.__vprint("Done.")
diff --git a/modoboa/extensions/amavis/migrations/0001_initial.py b/modoboa/extensions/amavis/migrations/0001_initial.py
deleted file mode 100644
index dea55f387..000000000
--- a/modoboa/extensions/amavis/migrations/0001_initial.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ]
-
- operations = [
- migrations.CreateModel(
- name='Maddr',
- fields=[
- ('partition_tag', models.IntegerField(unique=True, null=True, blank=True)),
- ('id', models.BigIntegerField(serialize=False, primary_key=True)),
- ('email', models.CharField(unique=True, max_length=255)),
- ('domain', models.CharField(max_length=765)),
- ],
- options={
- 'db_table': 'maddr',
- 'managed': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Mailaddr',
- fields=[
- ('id', models.IntegerField(serialize=False, primary_key=True)),
- ('priority', models.IntegerField()),
- ('email', models.CharField(unique=True, max_length=255)),
- ],
- options={
- 'db_table': 'mailaddr',
- 'managed': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Msgs',
- fields=[
- ('partition_tag', models.IntegerField(null=True, blank=True)),
- ('mail_id', models.CharField(max_length=12, serialize=False, primary_key=True)),
- ('secret_id', models.CharField(max_length=12, blank=True)),
- ('am_id', models.CharField(max_length=60)),
- ('time_num', models.IntegerField()),
- ('time_iso', models.CharField(max_length=48)),
- ('policy', models.CharField(max_length=765, blank=True)),
- ('client_addr', models.CharField(max_length=765, blank=True)),
- ('size', models.IntegerField()),
- ('originating', models.CharField(max_length=3)),
- ('content', models.CharField(max_length=1, blank=True)),
- ('quar_type', models.CharField(max_length=1, blank=True)),
- ('quar_loc', models.CharField(max_length=255, blank=True)),
- ('dsn_sent', models.CharField(max_length=3, blank=True)),
- ('spam_level', models.FloatField(null=True, blank=True)),
- ('message_id', models.CharField(max_length=765, blank=True)),
- ('from_addr', models.CharField(max_length=765, blank=True)),
- ('subject', models.CharField(max_length=765, blank=True)),
- ('host', models.CharField(max_length=765)),
- ],
- options={
- 'db_table': 'msgs',
- 'managed': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Msgrcpt',
- fields=[
- ('partition_tag', models.IntegerField(null=True, blank=True)),
- ('mail', models.ForeignKey(primary_key=True, serialize=False, to='amavis.Msgs')),
- ('rseqnum', models.IntegerField(default=0)),
- ('is_local', models.CharField(max_length=3)),
- ('content', models.CharField(max_length=3)),
- ('ds', models.CharField(max_length=3)),
- ('rs', models.CharField(max_length=3)),
- ('bl', models.CharField(max_length=3, blank=True)),
- ('wl', models.CharField(max_length=3, blank=True)),
- ('bspam_level', models.FloatField(null=True, blank=True)),
- ('smtp_resp', models.CharField(max_length=765, blank=True)),
- ],
- options={
- 'db_table': 'msgrcpt',
- 'managed': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Policy',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('policy_name', models.CharField(max_length=32, blank=True)),
- ('virus_lover', models.CharField(max_length=3, null=True, blank=True)),
- ('spam_lover', models.CharField(max_length=3, null=True, blank=True)),
- ('unchecked_lover', models.CharField(max_length=3, null=True, blank=True)),
- ('banned_files_lover', models.CharField(max_length=3, null=True, blank=True)),
- ('bad_header_lover', models.CharField(max_length=3, null=True, blank=True)),
- ('bypass_virus_checks', models.CharField(default=b'', choices=[(b'N', 'yes'), (b'Y', 'no'), (b'', 'default')], max_length=3, help_text="Bypass virus checks or not. Choose 'default' to use global settings.", null=True, verbose_name='Virus filter')),
- ('bypass_spam_checks', models.CharField(default=b'', choices=[(b'N', 'yes'), (b'Y', 'no'), (b'', 'default')], max_length=3, help_text="Bypass spam checks or not. Choose 'default' to use global settings.", null=True, verbose_name='Spam filter')),
- ('bypass_banned_checks', models.CharField(default=b'', choices=[(b'N', 'yes'), (b'Y', 'no'), (b'', 'default')], max_length=3, help_text="Bypass banned checks or not. Choose 'default' to use global settings.", null=True, verbose_name='Banned filter')),
- ('bypass_header_checks', models.CharField(max_length=3, null=True, blank=True)),
- ('virus_quarantine_to', models.CharField(max_length=192, null=True, blank=True)),
- ('spam_quarantine_to', models.CharField(max_length=192, null=True, blank=True)),
- ('banned_quarantine_to', models.CharField(max_length=192, null=True, blank=True)),
- ('unchecked_quarantine_to', models.CharField(max_length=192, null=True, blank=True)),
- ('bad_header_quarantine_to', models.CharField(max_length=192, null=True, blank=True)),
- ('clean_quarantine_to', models.CharField(max_length=192, null=True, blank=True)),
- ('archive_quarantine_to', models.CharField(max_length=192, null=True, blank=True)),
- ('spam_tag_level', models.FloatField(null=True, blank=True)),
- ('spam_tag2_level', models.FloatField(null=True, blank=True)),
- ('spam_tag3_level', models.FloatField(null=True, blank=True)),
- ('spam_kill_level', models.FloatField(null=True, blank=True)),
- ('spam_dsn_cutoff_level', models.FloatField(null=True, blank=True)),
- ('spam_quarantine_cutoff_level', models.FloatField(null=True, blank=True)),
- ('addr_extension_virus', models.CharField(max_length=192, null=True, blank=True)),
- ('addr_extension_spam', models.CharField(max_length=192, null=True, blank=True)),
- ('addr_extension_banned', models.CharField(max_length=192, null=True, blank=True)),
- ('addr_extension_bad_header', models.CharField(max_length=192, null=True, blank=True)),
- ('warnvirusrecip', models.CharField(max_length=3, null=True, blank=True)),
- ('warnbannedrecip', models.CharField(max_length=3, null=True, blank=True)),
- ('warnbadhrecip', models.CharField(max_length=3, null=True, blank=True)),
- ('newvirus_admin', models.CharField(max_length=192, null=True, blank=True)),
- ('virus_admin', models.CharField(max_length=192, null=True, blank=True)),
- ('banned_admin', models.CharField(max_length=192, null=True, blank=True)),
- ('bad_header_admin', models.CharField(max_length=192, null=True, blank=True)),
- ('spam_admin', models.CharField(max_length=192, null=True, blank=True)),
- ('spam_subject_tag', models.CharField(max_length=192, null=True, blank=True)),
- ('spam_subject_tag2', models.CharField(default=None, max_length=192, blank=True, help_text="Modify spam subject using the specified text. Choose 'default' to use global settings.", null=True, verbose_name='Spam marker')),
- ('spam_subject_tag3', models.CharField(max_length=192, null=True, blank=True)),
- ('message_size_limit', models.IntegerField(null=True, blank=True)),
- ('banned_rulenames', models.CharField(max_length=192, null=True, blank=True)),
- ('disclaimer_options', models.CharField(max_length=192, null=True, blank=True)),
- ('forward_method', models.CharField(max_length=192, null=True, blank=True)),
- ('sa_userconf', models.CharField(max_length=192, null=True, blank=True)),
- ('sa_username', models.CharField(max_length=192, null=True, blank=True)),
- ],
- options={
- 'db_table': 'policy',
- 'managed': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Quarantine',
- fields=[
- ('partition_tag', models.IntegerField(null=True, blank=True)),
- ('mail', models.ForeignKey(primary_key=True, serialize=False, to='amavis.Msgs')),
- ('chunk_ind', models.IntegerField()),
- ('mail_text', models.TextField()),
- ],
- options={
- 'ordering': ['-mail__time_num'],
- 'db_table': 'quarantine',
- 'managed': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Users',
- fields=[
- ('id', models.AutoField(serialize=False, primary_key=True)),
- ('priority', models.IntegerField()),
- ('email', models.CharField(unique=True, max_length=255)),
- ('fullname', models.CharField(max_length=765, blank=True)),
- ],
- options={
- 'db_table': 'users',
- 'managed': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Wblist',
- fields=[
- ('rid', models.IntegerField(serialize=False, primary_key=True)),
- ('sid', models.IntegerField(primary_key=True)),
- ('wb', models.CharField(max_length=30)),
- ],
- options={
- 'db_table': 'wblist',
- 'managed': False,
- },
- bases=(models.Model,),
- ),
- ]
diff --git a/modoboa/extensions/amavis/migrations/__init__.py b/modoboa/extensions/amavis/migrations/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/amavis/models.py b/modoboa/extensions/amavis/models.py
deleted file mode 100644
index 3a9876484..000000000
--- a/modoboa/extensions/amavis/models.py
+++ /dev/null
@@ -1,236 +0,0 @@
-# This is an auto-generated Django model module.
-# You'll have to do the following manually to clean this up:
-# * Rearrange models' order
-# * Make sure each model has one field with primary_key=True
-# Feel free to rename the models, but don't rename db_table values
-# or field names.
-#
-# Also note: You'll have to insert the output of
-# 'django-admin.py sqlcustom [appname]'into your database.
-#
-# Original Amavis version : 2.6.2
-
-from django.db import models
-from django.utils.translation import ugettext_lazy
-
-
-class Maddr(models.Model):
- partition_tag = models.IntegerField(unique=True, null=True, blank=True)
- id = models.BigIntegerField(primary_key=True)
- email = models.CharField(unique=True, max_length=255)
- domain = models.CharField(max_length=765)
-
- class Meta:
- db_table = u'maddr'
- managed = False
-
-
-class Mailaddr(models.Model):
- id = models.IntegerField(primary_key=True)
- priority = models.IntegerField()
- email = models.CharField(unique=True, max_length=255)
-
- class Meta:
- db_table = u'mailaddr'
- managed = False
-
-
-class Msgs(models.Model):
- partition_tag = models.IntegerField(null=True, blank=True)
- mail_id = models.CharField(max_length=12, primary_key=True)
- secret_id = models.CharField(max_length=12, blank=True)
- am_id = models.CharField(max_length=60)
- time_num = models.IntegerField()
- time_iso = models.CharField(max_length=48)
- sid = models.ForeignKey(Maddr, db_column='sid')
- policy = models.CharField(max_length=765, blank=True)
- client_addr = models.CharField(max_length=765, blank=True)
- size = models.IntegerField()
- originating = models.CharField(max_length=3)
- content = models.CharField(max_length=1, blank=True)
- quar_type = models.CharField(max_length=1, blank=True)
- quar_loc = models.CharField(max_length=255, blank=True)
- dsn_sent = models.CharField(max_length=3, blank=True)
- spam_level = models.FloatField(null=True, blank=True)
- message_id = models.CharField(max_length=765, blank=True)
- from_addr = models.CharField(max_length=765, blank=True)
- subject = models.CharField(max_length=765, blank=True)
- host = models.CharField(max_length=765)
-
- class Meta:
- db_table = u'msgs'
- managed = False
- unique_together = ('partition_tag', 'mail_id')
-
-
-class Msgrcpt(models.Model):
- partition_tag = models.IntegerField(null=True, blank=True)
- mail = models.ForeignKey(Msgs, primary_key=True)
- rid = models.ForeignKey(Maddr, db_column='rid')
- rseqnum = models.IntegerField(default=0)
- is_local = models.CharField(max_length=3)
- content = models.CharField(max_length=3)
- ds = models.CharField(max_length=3)
- rs = models.CharField(max_length=3)
- bl = models.CharField(max_length=3, blank=True)
- wl = models.CharField(max_length=3, blank=True)
- bspam_level = models.FloatField(null=True, blank=True)
- smtp_resp = models.CharField(max_length=765, blank=True)
-
- class Meta:
- db_table = u'msgrcpt'
- managed = False
- unique_together = ("partition_tag", "mail", "rseqnum")
-
-
-class Policy(models.Model):
- policy_name = models.CharField(max_length=32, blank=True)
- virus_lover = models.CharField(max_length=3, blank=True, null=True)
- spam_lover = models.CharField(max_length=3, blank=True, null=True)
- unchecked_lover = models.CharField(max_length=3, blank=True, null=True)
- banned_files_lover = models.CharField(max_length=3, blank=True, null=True)
- bad_header_lover = models.CharField(max_length=3, blank=True, null=True)
- bypass_virus_checks = models.CharField(
- ugettext_lazy("Virus filter"), default='', null=True,
- choices=(('N', ugettext_lazy('yes')),
- ('Y', ugettext_lazy('no')),
- ('', ugettext_lazy('default'))),
- max_length=3,
- help_text=ugettext_lazy(
- "Bypass virus checks or not. Choose 'default' to use global "
- "settings."
- )
- )
- bypass_spam_checks = models.CharField(
- ugettext_lazy("Spam filter"), default='', null=True,
- choices=(('N', ugettext_lazy('yes')),
- ('Y', ugettext_lazy('no')),
- ('', ugettext_lazy('default'))),
- max_length=3,
- help_text=ugettext_lazy(
- "Bypass spam checks or not. Choose 'default' to use global "
- "settings."
- )
- )
- bypass_banned_checks = models.CharField(
- ugettext_lazy("Banned filter"), default='', null=True,
- choices=(('N', ugettext_lazy('yes')),
- ('Y', ugettext_lazy('no')),
- ('', ugettext_lazy('default'))),
- max_length=3,
- help_text=ugettext_lazy(
- "Bypass banned checks or not. Choose 'default' to use global "
- "settings."
- )
- )
- bypass_header_checks = models.CharField(max_length=3, blank=True, null=True)
- virus_quarantine_to = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- spam_quarantine_to = models.CharField(max_length=192, blank=True, null=True)
- banned_quarantine_to = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- unchecked_quarantine_to = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- bad_header_quarantine_to = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- clean_quarantine_to = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- archive_quarantine_to = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- spam_tag_level = models.FloatField(null=True, blank=True)
- spam_tag2_level = models.FloatField(null=True, blank=True)
- spam_tag3_level = models.FloatField(null=True, blank=True)
- spam_kill_level = models.FloatField(null=True, blank=True)
- spam_dsn_cutoff_level = models.FloatField(null=True, blank=True)
- spam_quarantine_cutoff_level = models.FloatField(null=True, blank=True)
- addr_extension_virus = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- addr_extension_spam = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- addr_extension_banned = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- addr_extension_bad_header = models.CharField(
- max_length=192,
- blank=True,
- null=True)
- warnvirusrecip = models.CharField(max_length=3, blank=True, null=True)
- warnbannedrecip = models.CharField(max_length=3, blank=True, null=True)
- warnbadhrecip = models.CharField(max_length=3, blank=True, null=True)
- newvirus_admin = models.CharField(max_length=192, blank=True, null=True)
- virus_admin = models.CharField(max_length=192, blank=True, null=True)
- banned_admin = models.CharField(max_length=192, blank=True, null=True)
- bad_header_admin = models.CharField(max_length=192, blank=True, null=True)
- spam_admin = models.CharField(max_length=192, blank=True, null=True)
- spam_subject_tag = models.CharField(max_length=192, blank=True, null=True)
- spam_subject_tag2 = models.CharField(
- ugettext_lazy("Spam marker"), default=None,
- max_length=192, blank=True, null=True,
- help_text=ugettext_lazy(
- "Modify spam subject using the specified text. Choose 'default' to "
- "use global settings."
- )
- )
- spam_subject_tag3 = models.CharField(max_length=192, blank=True, null=True)
- message_size_limit = models.IntegerField(null=True, blank=True)
- banned_rulenames = models.CharField(max_length=192, blank=True, null=True)
- disclaimer_options = models.CharField(max_length=192, blank=True, null=True)
- forward_method = models.CharField(max_length=192, blank=True, null=True)
- sa_userconf = models.CharField(max_length=192, blank=True, null=True)
- sa_username = models.CharField(max_length=192, blank=True, null=True)
-
- class Meta:
- db_table = u'policy'
- managed = False
-
-
-class Quarantine(models.Model):
- partition_tag = models.IntegerField(null=True, blank=True)
- mail = models.ForeignKey(Msgs, primary_key=True)
- chunk_ind = models.IntegerField()
- mail_text = models.BinaryField()
-
- class Meta:
- db_table = u'quarantine'
- managed = False
- ordering = ["-mail__time_num"]
- unique_together = ("partition_tag", "mail", "chunk_ind")
-
-
-class Users(models.Model):
- id = models.AutoField(primary_key=True)
- priority = models.IntegerField()
- policy = models.ForeignKey(Policy)
- email = models.CharField(unique=True, max_length=255)
- fullname = models.CharField(max_length=765, blank=True)
-
- class Meta:
- db_table = u'users'
- managed = False
-
-
-class Wblist(models.Model):
- rid = models.IntegerField(primary_key=True)
- sid = models.IntegerField(primary_key=True)
- wb = models.CharField(max_length=30)
-
- class Meta:
- db_table = u'wblist'
- managed = False
diff --git a/modoboa/extensions/amavis/modo_extension.py b/modoboa/extensions/amavis/modo_extension.py
deleted file mode 100644
index 81b287a44..000000000
--- a/modoboa/extensions/amavis/modo_extension.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# coding: utf-8
-"""
-Amavis management frontend.
-
-Provides:
-
-* SQL quarantine management
-* Per-domain settings
-
-"""
-
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.extensions.admin.models import Domain
-from modoboa.lib import parameters
-
-from . import general_callbacks
-from .lib import create_user_and_policy, create_user_and_use_policy
-
-
-class Amavis(ModoExtension):
-
- """The Amavis extension."""
-
- name = "amavis"
- label = "Amavis frontend"
- version = "1.0"
- description = ugettext_lazy("Simple amavis management frontend")
- url = "quarantine"
- available_for_topredirection = True
-
- def load(self):
- from .app_settings import ParametersForm, UserSettings
-
- parameters.register(ParametersForm, "Amavis")
- parameters.register(UserSettings, ugettext_lazy("Quarantine"))
-
- def load_initial_data(self):
- """Create records for existing domains and co."""
- for dom in Domain.objects.all():
- policy = create_user_and_policy("@{0}".format(dom.name))
- for domalias in dom.domainalias_set.all():
- domalias_pattern = "@{0}".format(domalias.name)
- create_user_and_use_policy(domalias_pattern, policy)
-
- if not exts_pool.is_extension_installed(
- "modoboa.extensions.postfix_relay_domains"):
- return
- general_callbacks.create_relay_domains_records()
-
-exts_pool.register_extension(Amavis)
diff --git a/modoboa/extensions/amavis/sql_connector.py b/modoboa/extensions/amavis/sql_connector.py
deleted file mode 100644
index e21038d59..000000000
--- a/modoboa/extensions/amavis/sql_connector.py
+++ /dev/null
@@ -1,312 +0,0 @@
-"""
-SQL connector module.
-"""
-
-import datetime
-
-from django.db.models import Q
-
-from modoboa.extensions.admin.models import Domain
-from modoboa.lib.db_utils import db_type
-
-from .models import Quarantine, Msgrcpt, Maddr
-
-
-class SQLconnector(object):
-
- """
- This class handles all database operations.
- """
-
- ORDER_TRANSLATION_TABLE = {
- "type": "content",
- "score": "bspam_level",
- "date": "mail__time_num",
- "subject": "mail__subject",
- "from": "mail__from_addr",
- "to": "rid__email"
- }
-
- QUARANTINE_FIELDS = [
- "content",
- "bspam_level",
- "rs",
- "rid__email",
- "mail__from_addr",
- "mail__subject",
- "mail__mail_id",
- "mail__time_num",
- ]
-
- def __init__(self, user=None, navparams=None):
- """Constructor."""
- self.user = user
- self.navparams = navparams
- self.messages = None
-
- self._messages_count = None
-
- def _exec(self, query, args):
- """Execute a raw SQL query.
-
- :param string query: query to execute
- :param list args: a list of arguments to replace in :kw:`query`
- """
- from django.db import connections, transaction
-
- cursor = connections['amavis'].cursor()
- cursor.execute(query, args)
- transaction.commit_unless_managed(using='amavis')
-
- def _apply_msgrcpt_filters(self, flt):
- """Apply filters based on user's role.
-
- """
- if self.user.group == 'SimpleUsers':
- rcpts = [self.user.email]
- if self.user.mailbox_set.count():
- rcpts += self.user.mailbox_set.all()[0].alias_addresses
- return flt & Q(rid__email__in=rcpts)
- elif not self.user.is_superuser:
- doms = Domain.objects.get_for_admin(self.user)
- regexp = "(%s)" % '|'.join([dom.name for dom in doms])
- return flt & Q(rid__email__regex=regexp)
- return flt
-
- def _apply_extra_search_filter(self, crit, pattern):
- """Apply search filters using additional criterias.
-
- """
- if crit == "to":
- return Q(rid__email__contains=pattern)
- return None
-
- def _apply_extra_select_filters(self, messages):
- """Just a hook to apply additional filters to the queryset.
-
- """
- return messages
-
- def _get_quarantine_content(self):
- """Fetch quarantine content.
-
- Filters: rs, rid, content
- """
- flt = Q(rs__in=[' ', 'V', 'R', 'p', 'S', 'H']) \
- if self.navparams.get('viewrequests', '0') != '1' else Q(rs='p')
- flt = self._apply_msgrcpt_filters(flt)
- pattern = self.navparams.get("pattern", "")
- if pattern:
- criteria = self.navparams.get('criteria')
- if criteria == "both":
- criteria = "from_addr,subject,to"
- search_flt = None
- for crit in criteria.split(","):
- if crit == "from_addr":
- nfilter = Q(mail__from_addr__contains=pattern)
- elif crit == "subject":
- nfilter = Q(mail__subject__contains=pattern)
- else:
- nfilter = self._apply_extra_search_filter(crit, pattern)
- if nfilter is None:
- continue
- search_flt = nfilter \
- if search_flt is None else search_flt | nfilter
- if search_flt:
- flt &= search_flt
- msgtype = self.navparams.get('msgtype', None)
- if msgtype is not None:
- flt &= Q(content=msgtype)
-
- flt &= Q(
- mail__in=Quarantine.objects.filter(chunk_ind=1).values("mail_id")
- )
-
- messages = Msgrcpt.objects.select_related("mail", "rid").filter(flt)
- messages = self._apply_extra_select_filters(messages)
- return messages
-
- def messages_count(self):
- """Return the total number of messages living in the quarantine.
-
- We also store the built queryset for a later use.
- """
- if self.user is None or self.navparams is None:
- return None
- if self._messages_count is None:
- self.messages = self._get_quarantine_content()
- self.messages = self.messages.values(*self.QUARANTINE_FIELDS)
-
- order = self.navparams.get("order")
- if order is not None:
- sign = ""
- if order[0] == "-":
- sign = "-"
- order = order[1:]
- order = self.ORDER_TRANSLATION_TABLE[order]
- self.messages = self.messages.order_by(sign + order)
-
- self._messages_count = self.messages.count()
-
- return self._messages_count
-
- def fetch(self, start=None, stop=None):
- """Fetch a range of messages from the internal cache.
-
- """
- emails = []
- for qm in self.messages[start - 1:stop]:
- if qm["rs"] == 'D':
- continue
- m = {
- "from": qm["mail__from_addr"],
- "to": qm["rid__email"],
- "subject": qm["mail__subject"],
- "mailid": qm["mail__mail_id"],
- "date": datetime.datetime.fromtimestamp(qm["mail__time_num"]),
- "type": qm["content"],
- "score": qm["bspam_level"],
- "status": qm["rs"]
- }
- if qm["rs"] in ['', ' ']:
- m["class"] = "unseen"
- elif qm["rs"] == 'p':
- m["class"] = "pending"
- emails.append(m)
- return emails
-
- def get_recipient_message(self, address, mailid):
- """Retrieve a message for a given recipient.
- """
- return Msgrcpt.objects.get(mail=mailid, rid__email=address)
-
- def set_msgrcpt_status(self, address, mailid, status):
- """Change the status (rs field) of a message recipient.
-
- :param string status: status
- """
- addr = Maddr.objects.get(email=address)
- self._exec(
- "UPDATE msgrcpt SET rs=%s WHERE mail_id=%s AND rid=%s",
- [status, mailid, addr.id]
- )
-
- def get_domains_pending_requests(self, domains):
- """Retrieve pending release requests for a list of domains.
- """
- regexp = "(%s)" % '|'.join([dom.name for dom in domains])
- return Msgrcpt.objects.filter(rs='p', rid__email__regex=regexp)
-
- def get_pending_requests(self):
- """Return the number of requests currently pending."""
- rq = Q(rs='p')
- if not self.user.is_superuser:
- doms = Domain.objects.get_for_admin(self.user)
- if not doms.count():
- return 0
- regexp = "(%s)" % '|'.join([dom.name for dom in doms])
- doms_q = Q(rid__email__regex=regexp)
- rq &= doms_q
- return Msgrcpt.objects.filter(rq).count()
-
- def get_mail_content(self, mailid):
- """Retrieve the content of a message."""
- content = "".join([
- str(qmail.mail_text)
- for qmail in Quarantine.objects.filter(mail=mailid)
- ])
- if isinstance(content, unicode):
- content = content.encode("utf-8")
- return content
-
-
-class PgSQLconnector(SQLconnector):
-
- """
- The postgres version.
-
- Make use of ``QuerySet.extra`` and postgres ``convert_from``
- function to let the quarantine manager work as expected !
-
- The T4 alias is not a random choice. The generated query was
- dumped to found it. Be careful since it can changes with
- future Django versions...
-
- """
-
- def _apply_msgrcpt_filters(self, flt):
- """Return filters based on user's role. """
- self._where = []
- if self.user.group == 'SimpleUsers':
- rcpts = [self.user.email]
- if self.user.mailbox_set.count():
- rcpts += self.user.mailbox_set.all()[0].alias_addresses
- self._where.append(
- "convert_from(maddr.email, 'UTF8') IN (%s)"
- % (','.join(["'%s'" % rcpt for rcpt in rcpts])))
- elif not self.user.is_superuser:
- doms = Domain.objects.get_for_admin(self.user)
- regexp = "(%s)" % '|'.join([dom.name for dom in doms])
- self._where.append(
- "convert_from(maddr.email, 'UTF8') ~ '%s'" % regexp)
- return flt
-
- def _apply_extra_search_filter(self, crit, pattern):
- """Apply search filters using additional criterias."""
- if crit == "to":
- self._where.append(
- "convert_from(maddr.email, 'UTF8') LIKE '%%{0}%%'".format(
- pattern)
- )
- return None
-
- def _apply_extra_select_filters(self, messages):
- """Just a hook to apply additional filters to the queryset.
-
- """
- return messages.extra(where=self._where)
-
- def get_recipient_message(self, address, mailid):
- """Retrieve a message for a given recipient.
- """
- qset = Msgrcpt.objects.filter(mail=mailid).extra(
- where=["msgrcpt.rid=maddr.id",
- "convert_from(maddr.email, 'UTF8') = '%s'" % address],
- tables=['maddr']
- )
- return qset.all()[0]
-
- def get_domains_pending_requests(self, domains):
- """Retrieve pending release requests for a list of domains.
- """
- regexp = "(%s)" % '|'.join([dom.name for dom in domains])
- return Msgrcpt.objects.filter(rs='p').extra(
- where=["msgrcpt.rid=maddr.id",
- "convert_from(maddr.email, 'UTF8') ~ '%s'" % regexp],
- tables=['maddr']
- )
-
- def get_pending_requests(self):
- """Return the number of requests currently pending."""
- rq = Q(rs='p')
- if not self.user.is_superuser:
- doms = Domain.objects.get_for_admin(self.user)
- if not doms.count():
- return 0
- regexp = "(%s)" % '|'.join([dom.name for dom in doms])
- return Msgrcpt.objects.filter(rq).extra(
- where=["msgrcpt.rid=maddr.id",
- "convert_from(maddr.email, 'UTF8') ~ '%s'" % (regexp,)],
- tables=['maddr']
- ).count()
- return Msgrcpt.objects.filter(rq).count()
-
-
-def get_connector(**kwargs):
- """Return the appropriate *connector* class.
-
- The result depends on the DB engine in use.
- """
- if db_type("amavis") == 'postgres':
- return PgSQLconnector(**kwargs)
- return SQLconnector(**kwargs)
diff --git a/modoboa/extensions/amavis/sql_email.py b/modoboa/extensions/amavis/sql_email.py
deleted file mode 100644
index 201287462..000000000
--- a/modoboa/extensions/amavis/sql_email.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# coding: utf-8
-"""
-An email representation based on a database record.
-"""
-
-from django.template.loader import render_to_string
-
-from modoboa.lib.email_utils import Email
-
-from .sql_connector import get_connector
-
-
-class SQLemail(Email):
-
- """The SQL version of the Email class."""
-
- def __init__(self, *args, **kwargs):
- super(SQLemail, self).__init__(*args, **kwargs)
- fields = ["From", "To", "Cc", "Date", "Subject"]
- for f in fields:
- label = f
- self.headers += [
- {"name": label, "value": self.get_header(self.msg, f)}
- ]
- setattr(self, label, self.msg[f])
- qreason = self.get_header(self.msg, "X-Amavis-Alert")
- self.qtype = ""
- self.qreason = ""
- if qreason != "":
- if ',' in qreason:
- self.qtype, self.qreason = qreason.split(',', 1)
- elif qreason.startswith("BAD HEADER SECTION "):
- # Workaround for amavis <= 2.8.0 :p
- self.qtype = "BAD HEADER SECTION"
- self.qreason = qreason[19:]
-
- @property
- def msg(self):
- """Get message's content."""
- import email
-
- if self._msg is None:
- mail_text = get_connector().get_mail_content(self.mailid)
- self._msg = email.message_from_string(mail_text)
- self._parse(self._msg)
- return self._msg
-
- def render_headers(self, **kwargs):
- return render_to_string("amavis/mailheaders.html", {
- "qtype": self.qtype, "qreason": self.qreason,
- "headers": self.headers,
- })
diff --git a/modoboa/extensions/amavis/static/amavis/css/quarantine.css b/modoboa/extensions/amavis/static/amavis/css/quarantine.css
deleted file mode 100644
index 687d4fab2..000000000
--- a/modoboa/extensions/amavis/static/amavis/css/quarantine.css
+++ /dev/null
@@ -1,90 +0,0 @@
-@media (max-width: 400px){
- th#rstatus,
- td[name='rstatus'],
- th#type,
- td[name='type']{
- display: none;
- }
-}
-@media (max-width: 600px){
- th#subject,
- td[name='subject']{
- display: none;
- }
-}
-@media (max-width: 767px){
- th#to,
- td[name='to']{
- display: none;
- }
-}
-
-@media (max-width: 990px){
- #filters_bar,
- th#date,
- td[name='date']{
- display: none;
- }
-}
-
-#menubar {
- position: absolute;
- top: 51px;
- padding-left: 15px;
- padding-right: 15px;
- padding-top: 20px;
- padding-bottom: 10px;
- left: 0;
- right: 0;
- margin: 0;
- z-index: 10;
-}
-
-#menubar input[type="checkbox"] {
- margin: 0;
-}
-
-#listing {
- position: absolute;
- top: 125px;
- left: 0;
- right: 0;
- bottom: 0;
- margin: 0;
- overflow: auto;
- padding-left: 15px;
- padding-right: 15px;
-}
-
-#mailcontent {
- border: 0;
- margin: 0;
- padding: 0;
- width: 100%;
- height: 100%;
-}
-
-#emails tbody tr:hover {
- color: #0088cc;
-}
-
-thead tr {
- position: relative;
- z-index: 1;
-}
-
-td[name=type] span {
- cursor: pointer;
-}
-
-td.unseen {
- font-weight: bold;
-}
-
-td[class*=pending] {
- font-style: italic;
-}
-
-td[class*=openable] {
- cursor: pointer;
-}
\ No newline at end of file
diff --git a/modoboa/extensions/amavis/static/amavis/css/selfservice.css b/modoboa/extensions/amavis/static/amavis/css/selfservice.css
deleted file mode 100644
index 393c1c090..000000000
--- a/modoboa/extensions/amavis/static/amavis/css/selfservice.css
+++ /dev/null
@@ -1,21 +0,0 @@
-#menubar {
- padding-left: 15px;
- z-index: 10;
-}
-
-#listing {
- position: absolute;
- padding: 0px;
- right: 0;
- left: 0;
- bottom: 0;
- overflow: hidden;
-}
-
-#mailcontent {
- border: 0;
- margin: 0;
- padding: 0;
- width: 100%;
- height: 100%;
-}
\ No newline at end of file
diff --git a/modoboa/extensions/amavis/static/amavis/js/quarantine.js b/modoboa/extensions/amavis/static/amavis/js/quarantine.js
deleted file mode 100644
index 2885c28cb..000000000
--- a/modoboa/extensions/amavis/static/amavis/js/quarantine.js
+++ /dev/null
@@ -1,489 +0,0 @@
-/**
- * Return an instance of Quarantine.
- *
- * @constructor
- * @param {Object} options - instance options
- */
-var Quarantine = function(options) {
- Listing.call(this, options);
-};
-
-Quarantine.prototype = {
- constructor: Quarantine,
-
- defaults: {
- deflocation: "listing",
- main_table_id: "emails",
- scroll_container: "#listing",
- navigation_params: ["sort_order", "pattern", "criteria", "msgtype"],
- eor_message: gettext("No more message to show")
- },
-
- initialize: function(options) {
- this.options = $.extend({}, this.defaults, options);
- this.options.defcallback = $.proxy(this.listing_cb, this);
- Listing.prototype.initialize.call(this, this.options);
- this.register_navcallbacks();
- this.listen();
- this.set_msgtype();
-
- $(document).on('click', '#selectall', this.toggle_selection);
- this.initialize_searchfield();
- },
-
- /**
- * Search field initialization.
- */
- initialize_searchfield: function() {
- $("#searchfield").searchbar({
- navobj: this.navobj,
- pattern_changed: function(navobj) {
- navobj.setparam("reset_page", "true");
- }
- });
- },
-
- /**
- * Activate the button corresponding to the current message type
- * filter. If no message type is found, the 'All' button is
- * selected.
- */
- set_msgtype: function() {
- var msgtype = this.navobj.getparam('msgtype');
-
- $("input[name*=msgtype]").attr("checked", false)
- .parent().removeClass('active');
-
- if (msgtype !== undefined) {
- $("input[name=msgtype_" + msgtype + "]").attr("checked", true)
- .parent().addClass('active');
- } else {
- $("button[name=msgtype_all]").attr("checked", true)
- .parent().addClass('active');
- }
- },
-
- /**
- * Update the main page content.
- *
- * @this Quarantine
- * @param {Object} data - new content
- */
- update_page: function(data) {
- if (data.menu !== undefined) {
- $("#menubar").html(data.menu);
- this.initialize_searchfield();
- }
-
- if (data.listing !== undefined) {
- $("#listing").html(data.listing);
- }
- if (this.navobj.getbaseurl() == "listing") {
- this.update_listing(data);
- $(this.options.scroll_container).scrollTop(10);
- } else {
- this.update_listing(data, false);
- }
- },
-
- listen: function() {
- $(document).on("click", "td[class*=openable]", $.proxy(this.viewmail_loader, this));
- $(document).on("click", "a[name=selectmsgs]", $.proxy(this.selectmsgs, this));
- $(document).on("click", "a[name=release-multi]",
- $.proxy(this.release_selection, this));
- $(document).on("click", "a[name=delete-multi]",
- $.proxy(this.delete_selection, this));
- $(document).on("click", "a[name=mark-as-spam-multi]",
- $.proxy(this.mark_selection_as_spam, this));
- $(document).on("click", "a[name=mark-as-ham-multi]",
- $.proxy(this.mark_selection_as_ham, this));
- $(document).on("click", "a[name=viewrequests]",
- $.proxy(this.view_requests, this));
- $(document).on("click", "a[name=release]", $.proxy(this.release, this));
- $(document).on("click", "a[name=delete]", $.proxy(this.delete, this));
- $(document).on("click", "a[name=mark-as-spam]",
- $.proxy(this.mark_as_spam, this));
- $(document).on("click", "a[name=mark-as-ham]",
- $.proxy(this.mark_as_ham, this));
- $(document).on("click", "a[name=headers]", $.proxy(this.headers, this));
- $(document).on("click", "td[name=type] span", $.proxy(this.filter_by_type, this));
- $(document).on("click", "#filters label", $.proxy(this.filter_by_type, this));
- },
-
- load_page: function(e) {
- Listing.prototype.load_page.apply(this, arguments);
- this.navobj.delparam("rcpt").update();
- },
-
- /**
- * Return extra arguments used to fetch a page.
- *
- * @this Listing
- */
- get_load_page_args: function() {
- var args = Listing.prototype.get_load_page_args.call(this);
-
- args.scroll = true;
- return args;
- },
-
- /**
- * Calculate the bottom position of the scroll container.
- *
- * @param {Object} $element - scroll container object
- */
- calculate_bottom: function($element) {
- var emails_height = $("#emails").height();
-
- if (!emails_height) {
- return undefined;
- }
- return $("#emails").height() - $element.height();
- },
-
- view_requests: function(e) {
- e.preventDefault();
- this.navobj.setparam("viewrequests", "1").update();
- },
-
- viewmail_loader: function(e) {
- e.preventDefault();
- var $tr = $(e.target).parent();
- var $to = $tr.find("td[name=to]");
-
- this.navobj.baseurl($tr.attr("id"));
- if ($to.length) {
- this.navobj.setparam("rcpt", $to.html().trim());
- }
- this.navobj.update();
- },
-
- /*
- * Toggle message selection when the top checkbox's state is
- * modified.
- *
- * If it is checked, all messages are selected. Otherwise, the
- * current selection is resetted.
- */
- toggle_selection: function(e) {
- if (!$('#selectall').prop('checked')) {
- $("#emails").htmltable("clear_selection");
- return;
- }
- $("td[name*=selection]").each(function() {
- var $input = $(this).children('input');
- $input.prop('checked', true);
- $('#emails').htmltable('select_row', $(this).parent());
- });
- },
-
- /*
- * Select all messages of a specific type.
- */
- selectmsgs: function(e) {
- e.preventDefault();
- var type = get_target(e, 'a').attr("href");
- var counter = 0;
-
- $("td[name=type]").each(function() {
- var $this = $(this);
- if ($this.find('span').html().trim() == type) {
- var $input = $this.parent().children('td[name=selection]').children('input');
- $input.prop('checked', true);
- $('#emails').htmltable('select_row', $this.parent());
- counter++;
- }
- });
- if (counter) {
- $("#selectall").prop('checked', true);
- }
- },
-
- /**
- * Filter listing by message type (spam, virus, etc.)
- *
- * @param {Object} evt - event object
- */
- filter_by_type: function(evt) {
- var $target = $(evt.target);
- var msgtype;
-
- if ($target.is("span")) {
- msgtype = $target.html().trim();
- } else {
- msgtype = $target.children("input").attr("name").replace("msgtype_", "");
- }
-
- if (msgtype != 'all') {
- this.navobj.setparam('msgtype', msgtype);
- } else {
- this.navobj.delparam('msgtype');
- }
- this.navobj.update();
- },
-
- /**
- * Return the list of currently selected messages.
- *
- * @return {Array} - list of message IDs
- */
- get_current_selection: function() {
- var selection = [];
-
- this.htmltable.current_selection().each(function() {
- var $tr = $(this);
- var $to = $tr.find("td[name=to]");
-
- if ($to.length) {
- selection.push($to.html().trim() + " " + $tr.attr("id"));
- } else {
- selection.push($tr.attr("id"));
- }
- });
- return selection;
- },
-
- _send_selection: function(e, name, message) {
- var $link = $(e.target);
-
- e.preventDefault();
- if (!this.htmltable.current_selection().length ||
- !confirm(message)) {
- return;
- }
- var selection = this.get_current_selection();
-
- $.ajax({
- url: $link.attr("href"),
- data: "action=" + name + "&selection=" + selection.join(","),
- type: 'POST',
- dataType: 'json'
- }).done(
- $.proxy(this.action_cb, this)
- ).fail(function(jqxhr) {
- var data = $.parseJSON(jqxhr.responseText);
- $("body").notify("error", data.message);
- });
- },
-
- release_selection: function(e) {
- this._send_selection(e, "release", gettext("Release this selection?"));
- },
-
- delete_selection: function(e) {
- this._send_selection(e, "delete", gettext("Delete this selection?"));
- },
-
- /**
- * Show the recipient selection form inside a modal box.
- *
- * @param {Object} evt - event object
- * @param {string} ltype - learning type (spam or ham)
- */
- show_select_rcpt_form: function(evt, ltype, selection) {
- if (selection === undefined) {
- selection = this.get_current_selection();
- }
- var url = this.options.learning_recipient_url +
- "?type=" + ltype + "&selection=" +
- selection.join(",");
- var $this = this;
-
- modalbox(evt, null, url, function() {
- $(".submit").on("click", function(evt) {
- simple_ajax_form_post(evt, {
- formid: "learning_recipient_form",
- reload_on_success: false,
- success_cb: $.proxy($this.action_cb, $this)
- });
- });
- });
- },
-
- /**
- * Mark the current selection as spam.
- *
- * @param {Object} e - event object
- */
- mark_selection_as_spam: function(e) {
- if (this.options.check_learning_rcpt &&
- this.htmltable.current_selection().length) {
- this.show_select_rcpt_form(e, "spam");
- } else {
- this._send_selection(
- e, "mark_as_spam", gettext("Mark this selection as spam?"));
- }
- },
-
- /**
- * Mark the current selection as ham.
- *
- * @param {Object} e - event object
- */
- mark_selection_as_ham: function(e) {
- if (this.options.check_learning_rcpt &&
- this.htmltable.current_selection().length) {
- this.show_select_rcpt_form(e, "ham");
- } else {
- this._send_selection(
- e, "mark_as_ham", gettext("Mark this selection as non-spam?"));
- }
- },
-
- _send_action: function(e, message) {
- var $link = get_target(e, "a");
-
- e.preventDefault();
- if (!confirm(message)) {
- return;
- }
- $.ajax({
- url: $link.attr("href"),
- dataType: 'json',
- type: 'POST',
- data: {rcpt: get_parameter_by_name($link.attr("href"), 'rcpt')}
- }).done(
- $.proxy(this.action_cb, this)
- ).fail(function(jqxhr) {
- var data = $.parseJSON(jqxhr.responseText);
- $("body").notify("error", data.message);
- });
- },
-
- release : function(e) {
- this._send_action(e, gettext("Release this message?"));
- },
-
- delete: function(e) {
- this._send_action(e, gettext("Delete this message?"));
- },
-
- /**
- * Mark the current message as spam.
- *
- * @param {Object} e - event object
- */
- mark_as_spam: function(e) {
- if (this.options.check_learning_rcpt) {
- var $link = get_target(e, "a");
- var selection = get_parameter_by_name($link.attr("href"), "rcpt") +
- " " + $link.attr("data-mail-id");
- this.show_select_rcpt_form(e, "spam", [selection]);
- } else {
- this._send_action(e, gettext("Mark as spam?"));
- }
- },
-
- /**
- * Mark the current message as ham.
- *
- * @param {Object} e - event object
- */
- mark_as_ham: function(e) {
- if (this.options.check_learning_rcpt) {
- var $link = get_target(e, "a");
- var selection = get_parameter_by_name($link.attr("href"), "rcpt") +
- " " + $link.attr("data-mail-id");
- this.show_select_rcpt_form(e, "ham", [selection]);
- } else {
- this._send_action(e, gettext("Mark as non-spam?"));
- }
- },
-
- show_rawheaders: function($mailcontent) {
- $mailcontent.find("#rawheaders").removeClass("hidden");
- $mailcontent.find("#emailheaders").addClass("hidden");
- },
-
- headers: function(e) {
- e.preventDefault();
-
- var $link = get_target(e, "a");
- var $mailcontent = $("#mailcontent").contents();
- var $headers = $mailcontent.find("#emailheaders");
- var $rawheaders = $mailcontent.find("#rawheaders");
-
- if ($headers.hasClass("hidden")) {
- $link.html(gettext("View full headers"));
- $headers.removeClass("hidden");
- $rawheaders.addClass("hidden");
- return;
- }
- $link.html(gettext("Hide full headers"));
- if (!$rawheaders.length) {
- $.ajax({
- url: $link.attr("href"),
- global: false
- }).done($.proxy(function(data) {
- $mailcontent.find("#table-container").append($(data));
- this.show_rawheaders($mailcontent);
- }, this));
- return;
- }
- this.show_rawheaders($mailcontent);
- },
-
- update_params: function(e) {
- var $link = $(e.target);
- e.preventDefault();
- this.navobj.updateparams($link.attr("href")).update();
- },
-
- register_navcallbacks: function() {
- this.navobj.register_callback("_listing",
- $.proxy(this.listing_cb, this));
- this.navobj.register_callback("viewmail",
- $.proxy(this.viewmail_cb, this));
- },
-
- activate_buttons: function($tr) {
- $("a[name*=-multi]").removeClass('disabled');
- $("#selectall").prop('checked', true);
- },
-
- deactivate_buttons: function($tr) {
- if (!this.htmltable || !this.htmltable.current_selection().length) {
- $("a[name*=-multi]").addClass('disabled');
- $("#selectall").prop('checked', false);
- }
- },
-
- /**
- * Navigation callback: listing.
- *
- * @this Quarantine
- * @param {Object} data - ajax call response (JSON)
- */
- listing_cb: function(data) {
- this.update_page(data);
- this.navobj.delparam("rcpt").update();
- this.set_msgtype();
- $("#emails").htmltable({
- row_selected_event: this.activate_buttons,
- row_unselected_event: $.proxy(this.deactivate_buttons, this)
- });
- this.htmltable = $("#emails").data("htmltable");
- this.deactivate_buttons();
- if (this.navobj.hasparam("reset_page")) {
- this.navobj.delparam("reset_page").update(false, true);
- }
- $("#listing").css("overflow", "auto");
- },
-
- viewmail_cb: function(data) {
- this.update_page(data);
- $("#listing").css("overflow", "hidden");
- },
-
- action_cb: function(data) {
- if (data.reload) {
- this.navobj.update(true);
- }
- if (data.url) {
- this.navobj.parse_string(data.url, true).update(true);
- }
- $("body").notify("success", data.message, 2000);
- }
-};
-
-Quarantine.prototype = $.extend({}, Listing.prototype, Quarantine.prototype);
diff --git a/modoboa/extensions/amavis/static/amavis/js/selfservice.js b/modoboa/extensions/amavis/static/amavis/js/selfservice.js
deleted file mode 100644
index d634f9bfa..000000000
--- a/modoboa/extensions/amavis/static/amavis/js/selfservice.js
+++ /dev/null
@@ -1,30 +0,0 @@
-function send_action(e, message) {
- var $link = $(e.target);
-
- e.preventDefault();
- if (!confirm(message)) {
- return;
- }
- $.ajax({
- url: $link.attr("href"),
- dataType: 'json'
- }).done(function(data) {
- $("body").notify("success", data, 2000);
- });
-}
-
-function release(e) {
- send_action(e, gettext("Release this message?"));
-}
-
-function remove(e) {
- send_action(e, gettext("Delete this message?"));
-}
-
-$(document).ready(function() {
- $("#listing").css({
- top: $("#menubar").outerHeight() + 10
- });
- $(document).on("click", "a[name=release]", release);
- $(document).on("click", "a[name=delete]", remove);
-});
\ No newline at end of file
diff --git a/modoboa/extensions/amavis/templates/amavis/domain_content_filter.html b/modoboa/extensions/amavis/templates/amavis/domain_content_filter.html
deleted file mode 100644
index d669b7824..000000000
--- a/modoboa/extensions/amavis/templates/amavis/domain_content_filter.html
+++ /dev/null
@@ -1,18 +0,0 @@
-{% load i18n form_tags %}
-{% render_field form.bypass_virus_checks %}
-{% render_field form.bypass_spam_checks %}
-
-
-{% render_field form.spam_subject_tag2 activator=True activator_label=_("default") activator_size="col-sm-3" %}
-{% render_field form.bypass_banned_checks %}
diff --git a/modoboa/extensions/amavis/templates/amavis/email_list.html b/modoboa/extensions/amavis/templates/amavis/email_list.html
deleted file mode 100644
index 439d214c0..000000000
--- a/modoboa/extensions/amavis/templates/amavis/email_list.html
+++ /dev/null
@@ -1,31 +0,0 @@
-{% load i18n %}
-
-
diff --git a/modoboa/extensions/amavis/templates/amavis/emails_page.html b/modoboa/extensions/amavis/templates/amavis/emails_page.html
deleted file mode 100644
index 1b1233c6e..000000000
--- a/modoboa/extensions/amavis/templates/amavis/emails_page.html
+++ /dev/null
@@ -1,34 +0,0 @@
-{% load i18n %}
-{% load amavis_tags %}
-{% load static %}
-
-{% for email in email_list %}
-
-
-
-
-
- {{ email.type|msgtype_to_html }}
-
-
- {% if email.status == 'R' %}
-
- {% elif email.status == 'S' %}
-
- {% elif email.status == 'H' %}
-
- {% endif %}
-
- {{ email.score }}
- {{ email.to }}
-
- {{ email.from|truncatechars:30 }}
-
-
- {{ email.subject|truncatechars:30 }}
-
-
- {{ email.date|date:"SHORT_DATETIME_FORMAT" }}
-
-
-{% endfor %}
diff --git a/modoboa/extensions/amavis/templates/amavis/getmailcontent.html b/modoboa/extensions/amavis/templates/amavis/getmailcontent.html
deleted file mode 100644
index 579454343..000000000
--- a/modoboa/extensions/amavis/templates/amavis/getmailcontent.html
+++ /dev/null
@@ -1 +0,0 @@
-{% if pre %}{% endif %}{{ body }}{% if pre %} {% endif %}
\ No newline at end of file
diff --git a/modoboa/extensions/amavis/templates/amavis/index.html b/modoboa/extensions/amavis/templates/amavis/index.html
deleted file mode 100644
index 70a1a2ee7..000000000
--- a/modoboa/extensions/amavis/templates/amavis/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-{% extends "fluid.html" %}{% load i18n amavis_tags %}
-{% load static %}
-
-{% block pagetitle %}{% trans "Quarantine management" %}{% endblock %}
-
-{% block extra_css %}
-
-
-{% endblock %}
-
-{% block extra_js %}
-
-
-
-
-
-
-
-
-{% endblock %}
-
-{% block container_content %}
-
-
-{% endblock %}
diff --git a/modoboa/extensions/amavis/templates/amavis/mailheaders.html b/modoboa/extensions/amavis/templates/amavis/mailheaders.html
deleted file mode 100644
index 0ed8b3d61..000000000
--- a/modoboa/extensions/amavis/templates/amavis/mailheaders.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% extends "common/mailheaders.html" %}
-{% block emailheaders %}
-{% if qtype %}{{ qtype }} {{ qreason }}
{% endif %}
-{{ block.super }}
-{% endblock %}
diff --git a/modoboa/extensions/amavis/templates/amavis/main_action_bar.html b/modoboa/extensions/amavis/templates/amavis/main_action_bar.html
deleted file mode 100644
index 70b5222e6..000000000
--- a/modoboa/extensions/amavis/templates/amavis/main_action_bar.html
+++ /dev/null
@@ -1,79 +0,0 @@
-{% load lib_tags i18n %}
-
-
-
-
-
-
-
- {% if manual_learning %}
-
-
-
-
-
-
- {% endif %}
-
-
-
-
- {% include "common/email_searchbar.html" with extraopts=extraopts %}
-
-
-
-
-
diff --git a/modoboa/extensions/amavis/templates/amavis/notifications/pending_requests.html b/modoboa/extensions/amavis/templates/amavis/notifications/pending_requests.html
deleted file mode 100644
index a4729b339..000000000
--- a/modoboa/extensions/amavis/templates/amavis/notifications/pending_requests.html
+++ /dev/null
@@ -1,14 +0,0 @@
-{% load i18n lib_tags %}{% load url from future %}{% blocktrans count counter=total %}
-{{ counter }} release request is pending for action.
-{% plural %}
-{{ counter }} release requests are pending for action.
-{% endblocktrans %}
-{% trans "Sketch:" %}
-{% for msg in requests %}
-{% trans "From:" %} {{ msg.mail.sid.email }}
-{% trans "To:" %} {{ msg.rid.email }}
-{% trans "Date:" %} {{ msg.mail.time_num|fromunix|date:"DATETIME_FORMAT" }}
-{% trans "Subject:" %} {{ msg.mail.subject }}
-{% trans "Act on this message:" %} {{ baseurl }}{% url "amavis:index" %}#{{ msg.mail.mail_id }}/?rcpt={{ msg.rid.email }}
-{% endfor %}
-{% blocktrans %}Please visit {{ listingurl }} for a full listing.{% endblocktrans %}
diff --git a/modoboa/extensions/amavis/templates/amavis/viewheader.html b/modoboa/extensions/amavis/templates/amavis/viewheader.html
deleted file mode 100644
index 6e5efab6c..000000000
--- a/modoboa/extensions/amavis/templates/amavis/viewheader.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/modoboa/extensions/amavis/templates/amavis/viewmail_selfservice.html b/modoboa/extensions/amavis/templates/amavis/viewmail_selfservice.html
deleted file mode 100644
index 90ce332a0..000000000
--- a/modoboa/extensions/amavis/templates/amavis/viewmail_selfservice.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{% load i18n lib_tags amavis_tags %}{% load url from future %}
-{% load static %}
-
-
-
- Modoboa
-
-
-
-
-
-
-
-
-
- {% url "django.views.i18n.javascript_catalog" as catalog_url %}
-
-
-
-
-
-
-
diff --git a/modoboa/extensions/amavis/templatetags/__init__.py b/modoboa/extensions/amavis/templatetags/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/amavis/templatetags/amavis_tags.py b/modoboa/extensions/amavis/templatetags/amavis_tags.py
deleted file mode 100644
index f5d1a2c9a..000000000
--- a/modoboa/extensions/amavis/templatetags/amavis_tags.py
+++ /dev/null
@@ -1,132 +0,0 @@
-"""
-Amavis frontend template tags.
-"""
-
-from django import template
-from django.core.urlresolvers import reverse
-from django.template.loader import render_to_string
-from django.utils.safestring import mark_safe
-from django.utils.translation import ugettext as _
-
-from ..lib import manual_learning_enabled
-
-register = template.Library()
-
-
-@register.simple_tag
-def viewm_menu(user, mail_id, rcpt):
- """Menu displayed within the viewmail action."""
- entries = [
- {"name": "back",
- "url": "javascript:history.go(-1);",
- "img": "fa fa-arrow-left",
- "class": "btn-primary",
- "label": _("Back")},
- {"name": "release",
- "img": "fa fa-check",
- "class": "btn-success",
- "url": reverse('amavis:mail_release', args=[mail_id])
- + ("?rcpt=%s" % rcpt if rcpt else ""),
- "label": _("Release")},
- {"name": "delete",
- "class": "btn-danger",
- "img": "fa fa-trash",
- "url": reverse('amavis:mail_delete', args=[mail_id])
- + ("?rcpt=%s" % rcpt if rcpt else ""),
- "label": _("Delete")},
- {"name": "headers",
- "class": "btn-default",
- "url": reverse('amavis:headers_detail', args=[mail_id]),
- "label": _("View full headers")},
- ]
-
- if manual_learning_enabled(user):
- entries.insert(3, {
- "name": "process",
- "img": "fa fa-cog",
- "menu": [
- {"name": "mark-as-spam",
- "label": _("Mark as spam"),
- "url": reverse(
- "amavis:mail_mark_as_spam", args=[mail_id]
- ) + ("?rcpt=%s" % rcpt if rcpt else ""),
- "extra_attributes": {
- "data-mail-id": mail_id
- }},
- {"name": "mark-as-ham",
- "label": _("Mark as non-spam"),
- "url": reverse(
- "amavis:mail_mark_as_ham", args=[mail_id]
- ) + ("?rcpt=%s" % rcpt if rcpt else ""),
- "extra_attributes": {
- "data-mail-id": mail_id
- }}
- ]
- })
-
- menu = render_to_string('common/buttons_list.html',
- {"entries": entries, "extraclasses": "pull-left"})
-
- entries = [{"name": "close",
- "url": "javascript:history.go(-1);",
- "img": "icon-remove"}]
- menu += render_to_string(
- 'common/buttons_list.html',
- {"entries": entries, "extraclasses": "pull-right"}
- )
-
- return menu
-
-
-@register.simple_tag
-def viewm_menu_simple(user, mail_id, rcpt, secret_id=""):
- release_url = "{0}?rcpt={1}".format(
- reverse("amavis:mail_release", args=[mail_id]), rcpt)
- delete_url = "{0}?rcpt={1}".format(
- reverse("amavis:mail_delete", args=[mail_id]), rcpt)
- if secret_id:
- release_url += "&secret_id={0}".format(secret_id)
- delete_url += "&secret_id={0}".format(secret_id)
- entries = [
- {"name": "release",
- "img": "fa fa-check",
- "class": "btn-success",
- "url": release_url,
- "label": _("Release")},
- {"name": "delete",
- "img": "fa fa-trash",
- "class": "btn-danger",
- "url": delete_url,
- "label": _("Delete")},
- ]
-
- return render_to_string('common/buttons_list.html',
- {"entries": entries})
-
-
-@register.simple_tag
-def quar_menu(user):
- """Render the quarantine listing menu.
-
- :rtype: str
- :return: resulting HTML
- """
- extraopts = [{"name": "to", "label": _("To")}]
- return render_to_string("amavis/main_action_bar.html", {
- "extraopts": extraopts,
- "manual_learning": manual_learning_enabled(user)
- })
-
-
-@register.filter
-def msgtype_to_html(msgtype):
- """Transform a message type to a bootstrap label."""
- if msgtype in ["S", "V"]:
- color = 'danger'
- elif msgtype == "C":
- color = "success"
- else:
- color = "warning"
- return mark_safe(
- '%s ' % (color, msgtype)
- )
diff --git a/modoboa/extensions/amavis/urls.py b/modoboa/extensions/amavis/urls.py
deleted file mode 100644
index ae9ace7de..000000000
--- a/modoboa/extensions/amavis/urls.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns(
- 'modoboa.extensions.amavis.views',
-
- url(r'^$', 'index', name="index"),
- url(r'^listing/$', '_listing', name="_mail_list"),
- url(r'^listing/page/$', 'listing_page', name="mail_page"),
- url(r'^getmailcontent/(?P[\w\-\+]+)/$', 'getmailcontent',
- name="mailcontent_get"),
- url(r'^process/$', 'process', name="mail_process"),
- url(r'^delete/(?P[\w\-\+]+)/$', 'delete', name="mail_delete"),
- url(r'^release/(?P[\w\-\+]+)/$', 'release',
- name="mail_release"),
- url(r'^markspam/(?P[\w\-\+]+)/$', 'mark_as_spam',
- name="mail_mark_as_spam"),
- url(r'^markham/(?P[\w\-\+]+)/$', 'mark_as_ham',
- name="mail_mark_as_ham"),
- url(r'^learning_recipient/$', 'learning_recipient',
- name="learning_recipient_set"),
- url(r'^(?P[\w\-\+]+)/$', 'viewmail', name="mail_detail"),
- url(r'^(?P[\w\-\+]+)/headers/$', 'viewheaders',
- name="headers_detail"),
-)
diff --git a/modoboa/extensions/amavis/views.py b/modoboa/extensions/amavis/views.py
deleted file mode 100644
index 40fba3722..000000000
--- a/modoboa/extensions/amavis/views.py
+++ /dev/null
@@ -1,436 +0,0 @@
-# coding: utf-8
-"""
-Amavis quarantine views.
-"""
-import email
-
-import chardet
-
-from django.shortcuts import render
-from django.http import HttpResponseRedirect, Http404
-from django.template import Template, Context
-from django.utils.translation import ugettext as _, ungettext
-from django.core.urlresolvers import reverse
-from django.contrib.auth.decorators import login_required
-
-from modoboa.lib import parameters
-from modoboa.lib.exceptions import BadRequest
-from modoboa.lib.paginator import Paginator
-from modoboa.lib.web_utils import (
- getctx, render_to_json_response, _render_to_string
-)
-from modoboa.extensions.admin.models import Mailbox, Domain
-from modoboa.extensions.amavis.templatetags.amavis_tags import (
- quar_menu, viewm_menu
-)
-from .lib import (
- selfservice, AMrelease, QuarantineNavigationParameters,
- SpamassassinClient, manual_learning_enabled
-)
-from .forms import LearningRecipientForm
-from .models import Msgrcpt
-from .sql_connector import get_connector
-from .sql_email import SQLemail
-
-
-def empty_quarantine():
- """Shortcut to use when no content can be displayed."""
- content = "%s
" % _("Empty quarantine")
- ctx = getctx("ok", level=2, listing=content)
- return render_to_json_response(ctx)
-
-
-def get_listing_pages(request, connector):
- """Return listing pages."""
- paginator = Paginator(
- connector.messages_count(),
- int(parameters.get_user(request.user, "MESSAGES_PER_PAGE"))
- )
- page_id = int(connector.navparams.get("page"))
- page = paginator.getpage(page_id)
- if not page:
- return None
- pages = [page]
- if not page.has_next and page.has_previous and page.items < 40:
- pages = [paginator.getpage(page_id - 1)] + pages
- email_list = []
- for page in pages:
- email_list += connector.fetch(page.id_start, page.id_stop)
- return {"pages": [page.number for page in pages], "rows": email_list}
-
-
-@login_required
-def listing_page(request):
- """Return a listing page."""
- navparams = QuarantineNavigationParameters(request)
- previous_page_id = int(navparams["page"]) if "page" in navparams else None
- navparams.store()
-
- connector = get_connector(user=request.user, navparams=navparams)
- context = get_listing_pages(request, connector)
- if context is None:
- context = {"length": 0}
- navparams["page"] = previous_page_id
- else:
- context["rows"] = _render_to_string(
- request, "amavis/emails_page.html", {"email_list": context["rows"]}
- )
- return render_to_json_response(context)
-
-
-@login_required
-def _listing(request):
- """Listing initial view.
-
- Called the first time the listing page is displayed.
- """
- if not request.user.is_superuser and request.user.group != 'SimpleUsers':
- if not Domain.objects.get_for_admin(request.user).count():
- return empty_quarantine()
-
- navparams = QuarantineNavigationParameters(request)
- navparams.store()
-
- connector = get_connector(user=request.user, navparams=navparams)
- context = get_listing_pages(request, connector)
- if context is None:
- return empty_quarantine()
- context["listing"] = _render_to_string(
- request, "amavis/email_list.html", {"email_list": context["rows"]}
- )
- del context["rows"]
- if request.session.get('location', 'listing') != 'listing':
- context["menu"] = quar_menu(request.user)
- request.session["location"] = "listingx"
- return render_to_json_response(context)
-
-
-@login_required
-def index(request):
- """Default view."""
- check_learning_rcpt = "false"
- if parameters.get_admin("MANUAL_LEARNING") == "yes":
- if request.user.group != "SimpleUsers":
- user_level_learning = parameters.get_admin(
- "USER_LEVEL_LEARNING") == "yes"
- domain_level_learning = parameters.get_admin(
- "DOMAIN_LEVEL_LEARNING") == "yes"
- if user_level_learning or domain_level_learning:
- check_learning_rcpt = "true"
- return render(request, "amavis/index.html", dict(
- selection="quarantine", check_learning_rcpt=check_learning_rcpt
- ))
-
-
-def getmailcontent_selfservice(request, mail_id):
- mail = SQLemail(mail_id, mformat="plain", links="0")
- return render(request, "common/viewmail.html", {
- "headers": mail.render_headers(),
- "mailbody": mail.body
- })
-
-
-@selfservice(getmailcontent_selfservice)
-def getmailcontent(request, mail_id):
- mail = SQLemail(mail_id, mformat="plain", links="0")
- return render(request, "common/viewmail.html", {
- "headers": mail.render_headers(),
- "mailbody": mail.body
- })
-
-
-def viewmail_selfservice(request, mail_id,
- tplname="amavis/viewmail_selfservice.html"):
- rcpt = request.GET.get("rcpt", None)
- secret_id = request.GET.get("secret_id", "")
- if rcpt is None:
- raise Http404
- content = Template("""{% load url from future %}
-
-""").render(Context(dict(mail_id=mail_id)))
-
- return render(request, tplname, dict(
- mail_id=mail_id, rcpt=rcpt, secret_id=secret_id, content=content
- ))
-
-
-@selfservice(viewmail_selfservice)
-def viewmail(request, mail_id):
- rcpt = request.GET.get("rcpt", None)
- if rcpt is None:
- raise BadRequest(_("Invalid request"))
- if request.user.email == rcpt:
- get_connector().set_msgrcpt_status(rcpt, mail_id, 'V')
- elif request.user.mailbox_set.count():
- mb = Mailbox.objects.get(user=request.user)
- if rcpt == mb.full_address or rcpt in mb.alias_addresses:
- get_connector().set_msgrcpt_status(rcpt, mail_id, 'V')
-
- content = Template("""
-
-""").render(Context({"url": reverse("amavis:mailcontent_get", args=[mail_id])}))
- menu = viewm_menu(request.user, mail_id, rcpt)
- ctx = getctx("ok", menu=menu, listing=content)
- request.session['location'] = 'viewmail'
- return render_to_json_response(ctx)
-
-
-@login_required
-def viewheaders(request, mail_id):
- """Display message headers."""
- content = get_connector().get_mail_content(mail_id)
- msg = email.message_from_string(content)
- headers = []
- for name, value in msg.items():
- if value:
- result = chardet.detect(value)
- if result["encoding"] is not None:
- value = value.decode(result["encoding"])
- headers += [(name, value)]
- return render(request, 'amavis/viewheader.html', {
- "headers": headers
- })
-
-
-def check_mail_id(request, mail_id):
- if type(mail_id) in [str, unicode]:
- if "rcpt" in request.POST:
- mail_id = ["%s %s" % (request.POST["rcpt"], mail_id)]
- else:
- mail_id = [mail_id]
- return mail_id
-
-
-def get_user_valid_addresses(user):
- """Retrieve all valid addresses of a user."""
- valid_addresses = []
- if user.group == 'SimpleUsers':
- valid_addresses.append(user.email)
- try:
- mb = Mailbox.objects.get(user=user)
- except Mailbox.DoesNotExist:
- pass
- else:
- valid_addresses += mb.alias_addresses
- return valid_addresses
-
-
-def delete_selfservice(request, mail_id):
- rcpt = request.GET.get("rcpt", None)
- if rcpt is None:
- raise BadRequest(_("Invalid request"))
- try:
- get_connector().set_msgrcpt_status(rcpt, mail_id, 'D')
- except Msgrcpt.DoesNotExist:
- raise BadRequest(_("Invalid request"))
- return render_to_json_response(_("Message deleted"))
-
-
-@selfservice(delete_selfservice)
-def delete(request, mail_id):
- """Delete message selection.
-
- :param str mail_id: message unique identifier
- """
- mail_id = check_mail_id(request, mail_id)
- connector = get_connector()
- valid_addresses = get_user_valid_addresses(request.user)
- for mid in mail_id:
- r, i = mid.split()
- if valid_addresses and r not in valid_addresses:
- continue
- connector.set_msgrcpt_status(r, i, 'D')
- message = ungettext("%(count)d message deleted successfully",
- "%(count)d messages deleted successfully",
- len(mail_id)) % {"count": len(mail_id)}
- return render_to_json_response({
- "message": message,
- "url": QuarantineNavigationParameters(request).back_to_listing()
- })
-
-
-def release_selfservice(request, mail_id):
- rcpt = request.GET.get("rcpt", None)
- secret_id = request.GET.get("secret_id", None)
- if rcpt is None or secret_id is None:
- raise BadRequest(_("Invalid request"))
- connector = get_connector()
- try:
- msgrcpt = connector.get_recipient_message(rcpt, mail_id)
- except Msgrcpt.DoesNotExist:
- raise BadRequest(_("Invalid request"))
- if secret_id != msgrcpt.mail.secret_id:
- raise BadRequest(_("Invalid request"))
- if parameters.get_admin("USER_CAN_RELEASE") == "no":
- connector.set_msgrcpt_status(rcpt, mail_id, 'p')
- msg = _("Request sent")
- else:
- amr = AMrelease()
- result = amr.sendreq(mail_id, secret_id, rcpt)
- if result:
- connector.set_msgrcpt_status(rcpt, mail_id, 'R')
- msg = _("Message released")
- else:
- raise BadRequest(result)
- return render_to_json_response(msg)
-
-
-@selfservice(release_selfservice)
-def release(request, mail_id):
- """Release message selection.
-
- :param str mail_id: message unique identifier
- """
- mail_id = check_mail_id(request, mail_id)
- msgrcpts = []
- connector = get_connector()
- valid_addresses = get_user_valid_addresses(request.user)
- for mid in mail_id:
- r, i = mid.split()
- if valid_addresses and r not in valid_addresses:
- continue
- msgrcpts += [connector.get_recipient_message(r, i)]
- if request.user.group == "SimpleUsers" and \
- parameters.get_admin("USER_CAN_RELEASE") == "no":
- for msgrcpt in msgrcpts:
- connector.set_msgrcpt_status(
- msgrcpt.rid.email, msgrcpt.mail.mail_id, 'p'
- )
- message = ungettext("%(count)d request sent",
- "%(count)d requests sent",
- len(mail_id)) % {"count": len(mail_id)}
- return render_to_json_response({
- "message": message,
- "url": QuarantineNavigationParameters(request).back_to_listing()
- })
-
- amr = AMrelease()
- error = None
- for rcpt in msgrcpts:
- result = amr.sendreq(
- rcpt.mail.mail_id, rcpt.mail.secret_id, rcpt.rid.email
- )
- if result:
- connector.set_msgrcpt_status(rcpt.rid.email, rcpt.mail.mail_id, 'R')
- else:
- error = result
- break
-
- if not error:
- message = ungettext("%(count)d message released successfully",
- "%(count)d messages released successfully",
- len(mail_id)) % {"count": len(mail_id)}
- else:
- message = error
- status = 400 if error else 200
- return render_to_json_response({
- "message": message,
- "url": QuarantineNavigationParameters(request).back_to_listing()
- }, status=status)
-
-
-def mark_messages(request, selection, mtype, recipient_db=None):
- """Mark a selection of messages as spam.
-
- :param str selection: message unique identifier
- :param str mtype: type of marking (spam or ham)
- """
- if not manual_learning_enabled(request.user):
- return render_to_json_response({"status": "ok"})
- if recipient_db is None:
- recipient_db = (
- "user" if request.user.group == "SimpleUsers" else "global"
- )
- selection = check_mail_id(request, selection)
- connector = get_connector()
- saclient = SpamassassinClient(request.user, recipient_db)
- for item in selection:
- rcpt, mail_id = item.split()
- content = connector.get_mail_content(mail_id)
- result = saclient.learn_spam(rcpt, content) if mtype == "spam" \
- else saclient.learn_ham(rcpt, content)
- if not result:
- break
- connector.set_msgrcpt_status(rcpt, mail_id, mtype[0].upper())
- if saclient.error is None:
- saclient.done()
- message = ungettext("%(count)d message processed successfully",
- "%(count)d messages processed successfully",
- len(selection)) % {"count": len(selection)}
- else:
- message = saclient.error
- status = 400 if saclient.error else 200
- return render_to_json_response({
- "message": message, "reload": True
- }, status=status)
-
-
-@login_required
-def learning_recipient(request):
- """A view to select the recipient database of a learning action."""
- if request.method == "POST":
- form = LearningRecipientForm(request.user, request.POST)
- if form.is_valid():
- return mark_messages(
- request,
- form.cleaned_data["selection"].split(","),
- form.cleaned_data["ltype"],
- form.cleaned_data["recipient"]
- )
- return render_to_json_response(
- {"form_errors": form.errors}, status=400
- )
- ltype = request.GET.get("type", None)
- selection = request.GET.get("selection", None)
- if ltype is None or selection is None:
- raise BadRequest
- form = LearningRecipientForm(request.user)
- form.fields["ltype"].initial = ltype
- form.fields["selection"].initial = selection
- return render(request, "common/generic_modal_form.html", {
- "title": _("Select a database"),
- "formid": "learning_recipient_form",
- "action": reverse("amavis:learning_recipient_set"),
- "action_classes": "submit",
- "action_label": _("Validate"),
- "form": form
- })
-
-
-@login_required
-def mark_as_spam(request, mail_id):
- """Mark a single message as spam."""
- return mark_messages(request, mail_id, "spam")
-
-
-@login_required
-def mark_as_ham(request, mail_id):
- """Mark a single message as ham."""
- return mark_messages(request, mail_id, "ham")
-
-
-@login_required
-def process(request):
- """Process a selection of messages.
-
- The request must specify an action to execute against the
- selection.
-
- """
- action = request.POST.get("action", None)
- ids = request.POST.get("selection", "")
- ids = ids.split(",")
- if not ids or action is None:
- return HttpResponseRedirect(reverse("amavis:index"))
-
- if request.POST["action"] == "release":
- return release(request, ids)
-
- if request.POST["action"] == "delete":
- return delete(request, ids)
-
- if request.POST["action"] == "mark_as_spam":
- return mark_messages(request, ids, "spam")
-
- if request.POST["action"] == "mark_as_ham":
- return mark_messages(request, ids, "ham")
From 965b88adbd522ce3d77ddf1b8423d9ba33c88b58 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Feb 2015 10:34:25 +0100
Subject: [PATCH 03/25] Remove webmail extension.
---
modoboa/extensions/webmail/__init__.py | 0
modoboa/extensions/webmail/app_settings.py | 162 ---
modoboa/extensions/webmail/exceptions.py | 44 -
modoboa/extensions/webmail/forms.py | 211 ---
.../extensions/webmail/general_callbacks.py | 37 -
modoboa/extensions/webmail/lib/__init__.py | 33 -
modoboa/extensions/webmail/lib/attachments.py | 115 --
.../extensions/webmail/lib/fetch_parser.py | 233 ---
modoboa/extensions/webmail/lib/imapemail.py | 327 -----
modoboa/extensions/webmail/lib/imapheader.py | 113 --
modoboa/extensions/webmail/lib/imaputils.py | 788 ----------
modoboa/extensions/webmail/lib/sendmail.py | 65 -
modoboa/extensions/webmail/lib/signature.py | 31 -
modoboa/extensions/webmail/lib/utils.py | 46 -
modoboa/extensions/webmail/modo_extension.py | 25 -
.../static/webmail/css/attachments.css | 40 -
.../webmail/static/webmail/css/webmail.css | 303 ----
.../webmail/static/webmail/js/webmail.js | 1285 -----------------
.../templates/webmail/attachments.html | 29 -
.../webmail/templates/webmail/compose.html | 43 -
.../templates/webmail/compose_menubar.html | 13 -
.../webmail/templates/webmail/email_list.html | 25 -
.../webmail/templates/webmail/folder.html | 10 -
.../webmail/templates/webmail/folders.html | 4 -
.../webmail/templates/webmail/headers.html | 11 -
.../webmail/templates/webmail/index.html | 75 -
.../templates/webmail/main_action_bar.html | 9 -
.../templates/webmail/upload_done.html | 15 -
.../webmail/templatetags/__init__.py | 0
.../webmail/templatetags/webmail_tags.py | 221 ---
modoboa/extensions/webmail/urls.py | 25 -
modoboa/extensions/webmail/views.py | 618 --------
32 files changed, 4956 deletions(-)
delete mode 100644 modoboa/extensions/webmail/__init__.py
delete mode 100644 modoboa/extensions/webmail/app_settings.py
delete mode 100644 modoboa/extensions/webmail/exceptions.py
delete mode 100644 modoboa/extensions/webmail/forms.py
delete mode 100644 modoboa/extensions/webmail/general_callbacks.py
delete mode 100644 modoboa/extensions/webmail/lib/__init__.py
delete mode 100644 modoboa/extensions/webmail/lib/attachments.py
delete mode 100644 modoboa/extensions/webmail/lib/fetch_parser.py
delete mode 100644 modoboa/extensions/webmail/lib/imapemail.py
delete mode 100644 modoboa/extensions/webmail/lib/imapheader.py
delete mode 100644 modoboa/extensions/webmail/lib/imaputils.py
delete mode 100644 modoboa/extensions/webmail/lib/sendmail.py
delete mode 100644 modoboa/extensions/webmail/lib/signature.py
delete mode 100644 modoboa/extensions/webmail/lib/utils.py
delete mode 100644 modoboa/extensions/webmail/modo_extension.py
delete mode 100644 modoboa/extensions/webmail/static/webmail/css/attachments.css
delete mode 100644 modoboa/extensions/webmail/static/webmail/css/webmail.css
delete mode 100644 modoboa/extensions/webmail/static/webmail/js/webmail.js
delete mode 100644 modoboa/extensions/webmail/templates/webmail/attachments.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/compose.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/compose_menubar.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/email_list.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/folder.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/folders.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/headers.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/index.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/main_action_bar.html
delete mode 100644 modoboa/extensions/webmail/templates/webmail/upload_done.html
delete mode 100644 modoboa/extensions/webmail/templatetags/__init__.py
delete mode 100644 modoboa/extensions/webmail/templatetags/webmail_tags.py
delete mode 100644 modoboa/extensions/webmail/urls.py
delete mode 100644 modoboa/extensions/webmail/views.py
diff --git a/modoboa/extensions/webmail/__init__.py b/modoboa/extensions/webmail/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/webmail/app_settings.py b/modoboa/extensions/webmail/app_settings.py
deleted file mode 100644
index 70e371332..000000000
--- a/modoboa/extensions/webmail/app_settings.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# coding: utf-8
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from modoboa.lib.parameters import AdminParametersForm, UserParametersForm
-from modoboa.lib.form_utils import SeparatorField, YesNoField, InlineRadioSelect
-
-
-class ParametersForm(AdminParametersForm):
- app = "webmail"
-
- sep3 = SeparatorField(label=_("General"))
-
- max_attachment_size = forms.CharField(
- label=_("Maximum attachment size"),
- initial="2048",
- help_text=_(
- "Maximum attachment size in bytes (or KB, MB, GB if specified)")
- )
-
- sep1 = SeparatorField(label=_("IMAP settings"))
-
- imap_server = forms.CharField(
- label=_("Server address"),
- initial="127.0.0.1",
- help_text=_("Address of your IMAP server")
- )
-
- imap_secured = YesNoField(
- label=_("Use a secured connection"),
- initial="no",
- help_text=_("Use a secured connection to access IMAP server")
- )
-
- imap_port = forms.IntegerField(
- label=_("Server port"),
- initial=143,
- help_text=_("Listening port of your IMAP server")
- )
-
- sep2 = SeparatorField(label=_("SMTP settings"))
-
- smtp_server = forms.CharField(
- label=_("Server address"),
- initial="127.0.0.1",
- help_text=_("Address of your SMTP server")
- )
-
- smtp_secured_mode = forms.ChoiceField(
- label=_("Secured connection mode"),
- choices=[("none", _("None")),
- ("starttls", "STARTTLS"),
- ("ssl", "SSL/TLS")],
- initial="none",
- help_text=_("Use a secured connection to access SMTP server"),
- widget=InlineRadioSelect
- )
-
- smtp_port = forms.IntegerField(
- label=_("Server port"),
- initial=25,
- help_text=_("Listening port of your SMTP server")
- )
-
- smtp_authentication = YesNoField(
- label=_("Authentication required"),
- initial="no",
- help_text=_("Server needs authentication")
- )
-
-
-class UserSettings(UserParametersForm):
- app = "webmail"
-
- sep1 = SeparatorField(label=_("Display"))
-
- displaymode = forms.ChoiceField(
- initial="plain",
- label=_("Default message display mode"),
- choices=[("html", "html"), ("plain", "text")],
- help_text=_("The default mode used when displaying a message"),
- widget=InlineRadioSelect()
- )
-
- enable_links = YesNoField(
- initial="no",
- label=_("Enable HTML links display"),
- help_text=_("Enable/Disable HTML links display")
- )
-
- messages_per_page = forms.IntegerField(
- initial=40,
- label=_("Number of displayed emails per page"),
- help_text=_("Sets the maximum number of messages displayed in a page")
- )
-
- refresh_interval = forms.IntegerField(
- initial=300,
- label=_("Listing refresh rate"),
- help_text=_("Automatic folder refresh rate (in seconds)")
- )
-
- mboxes_col_width = forms.IntegerField(
- initial=200,
- label=_("Mailboxes container's width"),
- help_text=_("The width of the mailbox list container")
- )
-
- sep2 = SeparatorField(label=_("Mailboxes"))
-
- trash_folder = forms.CharField(
- initial="Trash",
- label=_("Trash folder"),
- help_text=_("Folder where deleted messages go")
- )
-
- sent_folder = forms.CharField(
- initial="Sent",
- label=_("Sent folder"),
- help_text=_("Folder where copies of sent messages go")
- )
-
- drafts_folder = forms.CharField(
- initial="Drafts",
- label=_("Drafts folder"),
- help_text=_("Folder where drafts go")
- )
-
- sep3 = SeparatorField(label=_("Composing messages"))
-
- editor = forms.ChoiceField(
- initial="plain",
- label=_("Default editor"),
- choices=[("html", "html"), ("plain", "text")],
- help_text=_("The default editor to use when composing a message"),
- widget=InlineRadioSelect()
- )
-
- signature = forms.CharField(
- initial="",
- label=_("Signature text"),
- help_text=_("User defined email signature"),
- required=False
- )
-
- visibility_rules = {
- "enable_links": "displaymode=html"
- }
-
- @staticmethod
- def has_access(user):
- return user.mailbox_set.count() != 0
-
- def clean_mboxes_col_width(self):
- """Check if the entered value is a positive integer.
-
- It must also be different from 0.
- """
- if self.cleaned_data['mboxes_col_width'] <= 0:
- raise forms.ValidationError(
- _('Value must be a positive integer (> 0)')
- )
- return self.cleaned_data['mboxes_col_width']
diff --git a/modoboa/extensions/webmail/exceptions.py b/modoboa/extensions/webmail/exceptions.py
deleted file mode 100644
index e5012ab8a..000000000
--- a/modoboa/extensions/webmail/exceptions.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# coding: utf-8
-"""
-:mod:`exceptions` --- Webmail custom exceptions
------------------------------------------------
-
-"""
-import re
-from django.utils.translation import ugettext as _
-from modoboa.lib.exceptions import ModoboaException, InternalError
-
-
-class WebmailInternalError(InternalError):
- errorexpr = re.compile(r'\[([^\]]+)\]\s*([^\.]+)')
-
- def __init__(self, reason, ajax=False):
- match = WebmailInternalError.errorexpr.match(reason)
- if not match:
- self.reason = reason
- else:
- self.reason = "%s: %s" % (_("Server response"), match.group(2))
- self.ajax = ajax
-
- def __str__(self):
- return self.reason
-
-
-class UnknownAction(ModoboaException):
-
- """
- Use this exception when the webmail encounter an unknown action.
- """
- http_code = 404
-
- def __init__(self):
- super(UnknownAction, self).__init__(_("Unknown action"))
-
-
-class ImapError(ModoboaException):
-
- def __init__(self, reason):
- self.reason = reason
-
- def __str__(self):
- return str(self.reason)
diff --git a/modoboa/extensions/webmail/forms.py b/modoboa/extensions/webmail/forms.py
deleted file mode 100644
index c377fc91b..000000000
--- a/modoboa/extensions/webmail/forms.py
+++ /dev/null
@@ -1,211 +0,0 @@
-# coding: utf-8
-from email.mime.multipart import MIMEMultipart
-from email.mime.text import MIMEText
-
-import lxml.html
-
-from django import forms
-from django.conf import settings
-from django.utils.translation import ugettext_lazy as _
-
-from modoboa.lib import parameters
-from modoboa.lib.email_utils import set_email_headers
-from .lib import (
- ImapEmail, create_mail_attachment
-)
-
-
-def html2plaintext(content):
- """HTML to plain text translation.
-
- :param content: some HTML content
- """
- if not content:
- return ""
- html = lxml.html.fromstring(content)
- plaintext = ""
- for ch in html.iter():
- p = None
- if ch.text is not None:
- p = ch.text.strip('\r\t\n')
- if ch.tag == "img":
- p = ch.get("alt")
- if p is None:
- continue
- plaintext += p + "\n"
- return plaintext
-
-
-def make_body_images_inline(body):
- """Looks for images inside the body and make them inline.
-
- Before sending a message in HTML format, it is necessary to find
- all img tags contained in the body in order to rewrite them. For
- example, icons provided by CKeditor are stored on the server
- filesystem and not accessible from the outside. We must embark
- them as parts of the MIME message if we want recipients to
- display them correctly.
-
- :param body: the HTML body to parse
- """
- import os
- from email.mime.image import MIMEImage
- from urlparse import urlparse
-
- html = lxml.html.fromstring(body)
- parts = []
- for tag in html.iter("img"):
- src = tag.get("src")
- if src is None:
- continue
- o = urlparse(src)
- path = os.path.join(settings.MODOBOA_DIR, o.path[1:])
- if not os.path.exists(path):
- continue
- fname = os.path.basename(path)
- cid = "%s@modoboa" % os.path.splitext(fname)[0]
- tag.set("src", "cid:%s" % cid)
- with open(path, "rb") as fp:
- part = MIMEImage(fp.read())
- part["Content-ID"] = "<%s>" % cid
- part.replace_header(
- "Content-Type", '%s; name="%s"' % (part["Content-Type"], fname)
- )
- part["Content-Disposition"] = "inline"
- parts.append(part)
- return lxml.html.tostring(html), parts
-
-
-class ComposeMailForm(forms.Form):
-
- """Compose mail form."""
-
- to = forms.CharField(label=_("To"))
- cc = forms.CharField(label=_("Cc"), required=False)
- cci = forms.CharField(label=_("Cci"), required=False)
- subject = forms.CharField(
- label=_("Subject"),
- max_length=255,
- required=False
- )
- origmsgid = forms.CharField(label="", required=False)
- body = forms.CharField(required=False)
-
- def __init__(self, *args, **kwargs):
- """Custom constructor."""
- super(ComposeMailForm, self).__init__(*args, **kwargs)
- self.field_widths = {
- "cc": "11",
- "cci": "11",
- "subject": "11"
- }
-
- def _html_msg(self):
- """Create a multipart message.
-
- We attach two alternatives:
- * text/html
- * text/plain
- """
- msg = MIMEMultipart(_subtype="related")
- submsg = MIMEMultipart(_subtype="alternative")
- body = self.cleaned_data["body"]
- charset = "utf-8"
- if body:
- tbody = html2plaintext(body)
- body, images = make_body_images_inline(body)
- else:
- tbody = ""
- images = []
- submsg.attach(
- MIMEText(tbody.encode(charset), _subtype="plain", _charset=charset)
- )
- submsg.attach(
- MIMEText(body.encode(charset), _subtype="html", _charset=charset)
- )
- msg.attach(submsg)
- for img in images:
- msg.attach(img)
- return msg
-
- def _plain_msg(self):
- """Create a simple text message.
- """
- charset = "utf-8"
- text = MIMEText(self.cleaned_data["body"].encode(charset),
- _subtype="plain", _charset=charset)
- return text
-
- def _build_msg(self, request):
- """Convert form's content to a MIME message.
- """
- editormode = parameters.get_user(request.user, "EDITOR")
- msg = getattr(self, "_%s_msg" % editormode)()
-
- if request.session["compose_mail"]["attachments"]:
- wrapper = MIMEMultipart(_subtype="mixed")
- wrapper.attach(msg)
- for attdef in request.session["compose_mail"]["attachments"]:
- wrapper.attach(create_mail_attachment(attdef))
- msg = wrapper
- return msg
-
- def to_msg(self, request):
- """Convert form's content to an object ready to send.
-
- We set headers at the end to be sure no one will override
- them.
-
- """
- msg = self._build_msg(request)
- set_email_headers(
- msg, self.cleaned_data["subject"], request.user.encoded_address,
- self.cleaned_data['to']
- )
- origmsgid = self.cleaned_data.get("origmsgid", None)
- if origmsgid:
- msg["References"] = msg["In-Reply-To"] = origmsgid
- return msg
-
-
-class ForwardMailForm(ComposeMailForm):
-
- """Forward mail form."""
-
- def _build_msg(self, request):
- """Convert form's content to a MIME message.
-
- We also add original attachments (if any) to the new message.
- """
- from modoboa.extensions.webmail.lib import decode_payload
-
- mbox = request.GET.get("mbox", None)
- mailid = request.GET.get("mailid", None)
- msg = super(ForwardMailForm, self)._build_msg(request)
- origmsg = ImapEmail(request, False, "%s:%s" % (mbox, mailid))
- if origmsg.attachments:
- if not msg.is_multipart or not msg.get_content_subtype() == "mixed":
- wrapper = MIMEMultipart(_subtype="mixed")
- wrapper.attach(msg)
- msg = wrapper
- for attpart, fname in origmsg.attachments.items():
- attdef, payload = origmsg.fetch_attachment(attpart)
- attdef["fname"] = fname
- msg.attach(create_mail_attachment(
- attdef, decode_payload(attdef["encoding"], payload)
- ))
- return msg
-
-
-class FolderForm(forms.Form):
- oldname = forms.CharField(
- label="",
- widget=forms.HiddenInput(attrs={"class": "form-control"}),
- required=False
- )
- name = forms.CharField(
- widget=forms.TextInput(attrs={"class": "form-control"}))
-
-
-class AttachmentForm(forms.Form):
- attachment = forms.FileField(label=_("Select a file"))
diff --git a/modoboa/extensions/webmail/general_callbacks.py b/modoboa/extensions/webmail/general_callbacks.py
deleted file mode 100644
index bfc496b92..000000000
--- a/modoboa/extensions/webmail/general_callbacks.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from django.utils.translation import ugettext as _
-from django.core.urlresolvers import reverse
-from modoboa.lib import events
-
-
-@events.observe("UserMenuDisplay")
-def menu(target, user):
- if target != "top_menu":
- return []
- if not user.mailbox_set.count():
- return []
- return [
- {"name": "webmail",
- "label": _("Webmail"),
- "url": reverse("webmail:index")},
- ]
-
-
-@events.observe("UserLogout")
-def userlogout(request):
- from .lib import IMAPconnector
- from .exceptions import ImapError
-
- if not request.user.mailbox_set.count():
- return
- try:
- m = IMAPconnector(user=request.user.username,
- password=request.session["password"])
- except Exception:
- # TODO silent exception are bad : we should at least log it
- return
-
- # The following statement may fail under Python 2.6...
- try:
- m.logout()
- except ImapError:
- pass
diff --git a/modoboa/extensions/webmail/lib/__init__.py b/modoboa/extensions/webmail/lib/__init__.py
deleted file mode 100644
index 0f0b166b3..000000000
--- a/modoboa/extensions/webmail/lib/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from .attachments import (
- create_mail_attachment, save_attachment, clean_attachments,
- set_compose_session, AttachmentUploadHandler
-)
-from .imapemail import ImapEmail, ReplyModifier, ForwardModifier
-from .imaputils import (
- BodyStructure, IMAPconnector, get_imapconnector, separate_mailbox
-)
-from .signature import EmailSignature
-from .utils import decode_payload, WebmailNavigationParameters
-from .sendmail import send_mail
-from .fetch_parser import parse_fetch_response
-
-
-__all__ = [
- 'AttachmentUploadHandler',
- 'BodyStructure',
- 'EmailSignature',
- 'ForwardModifier',
- 'IMAPconnector',
- 'ImapEmail',
- 'ReplyModifier',
- 'WebmailNavigationParameters',
- 'clean_attachments',
- 'create_mail_attachment',
- 'decode_payload',
- 'get_imapconnector',
- 'parse_fetch_response',
- 'save_attachment',
- 'send_mail',
- 'separate_mailbox',
- 'set_compose_session',
-]
diff --git a/modoboa/extensions/webmail/lib/attachments.py b/modoboa/extensions/webmail/lib/attachments.py
deleted file mode 100644
index 7da2ed898..000000000
--- a/modoboa/extensions/webmail/lib/attachments.py
+++ /dev/null
@@ -1,115 +0,0 @@
-import os
-from rfc6266 import build_header
-from django.conf import settings
-from django.core.files.uploadhandler import FileUploadHandler, SkipFile
-from modoboa.lib import parameters
-from modoboa.lib.exceptions import InternalError
-from modoboa.lib.web_utils import size2integer
-
-
-def set_compose_session(request):
- """Initialize a new "compose" session.
-
- It is used to keep track of attachments defined with a new
- message. Each new message will be associated with a unique ID (in
- order to avoid conflicts between users).
-
- :param request: a Request object.
- :return: the new unique ID.
- """
- import uuid
- randid = str(uuid.uuid4()).replace("-", "")
- request.session["compose_mail"] = {"id": randid, "attachments": []}
- return randid
-
-
-def save_attachment(f):
- """Save a new attachment to the filesystem.
-
- The attachment is not saved using its own name to the
- filesystem. To avoid conflicts, a random name is generated and
- used instead.
-
- :param f: an uploaded file object (see Django's documentation)
- :return: the new random name
- """
- from tempfile import NamedTemporaryFile
-
- dstdir = os.path.join(settings.MEDIA_ROOT, "webmail")
- try:
- fp = NamedTemporaryFile(dir=dstdir, delete=False)
- except Exception as e:
- raise InternalError(str(e))
- for chunk in f.chunks():
- fp.write(chunk)
- fp.close()
- return fp.name
-
-
-def clean_attachments(attlist):
- """Remove all attachments from the filesystem
-
- :param attlist: a list of 2-uple. Each element must contain the
- following information : (random name, real name).
- """
- for att in attlist:
- fullpath = os.path.join(settings.MEDIA_ROOT, "webmail", att["tmpname"])
- try:
- os.remove(fullpath)
- except OSError:
- pass
-
-
-def create_mail_attachment(attdef, payload=None):
- """Create the MIME part corresponding to the given attachment.
-
- Mandatory keys: 'fname', 'tmpname', 'content-type'
-
- :param attdef: a dictionary containing the attachment definition
- :return: a MIMEBase object
- """
- from email import Encoders
- from email.mime.base import MIMEBase
-
- if "content-type" in attdef:
- maintype, subtype = attdef["content-type"].split("/")
- elif "Content-Type" in attdef:
- maintype, subtype = attdef["Content-Type"].split("/")
- else:
- return None
- res = MIMEBase(maintype, subtype)
- if payload is None:
- with open(os.path.join(
- settings.MEDIA_ROOT, "webmail", attdef["tmpname"]), "rb") as fp:
- res.set_payload(fp.read())
- else:
- res.set_payload(payload)
- Encoders.encode_base64(res)
- if isinstance(attdef['fname'], str):
- attdef['fname'] = attdef['fname'].decode('utf-8')
- res['Content-Disposition'] = build_header(attdef['fname'])
- return res
-
-
-class AttachmentUploadHandler(FileUploadHandler):
-
- """
- Simple upload handler to limit the size of the attachments users
- can upload.
- """
-
- def __init__(self, request=None):
- super(AttachmentUploadHandler, self).__init__(request)
- self.total_upload = 0
- self.toobig = False
- self.maxsize = size2integer(parameters.get_admin("MAX_ATTACHMENT_SIZE"))
-
- def receive_data_chunk(self, raw_data, start):
- self.total_upload += len(raw_data)
- if self.total_upload >= self.maxsize:
- self.toobig = True
- raise SkipFile()
- return raw_data
-
- def file_complete(self, file_size):
- return None
diff --git a/modoboa/extensions/webmail/lib/fetch_parser.py b/modoboa/extensions/webmail/lib/fetch_parser.py
deleted file mode 100644
index 8d83cdf2d..000000000
--- a/modoboa/extensions/webmail/lib/fetch_parser.py
+++ /dev/null
@@ -1,233 +0,0 @@
-# coding: utf-8
-"""
-:mod:`fetch_parser` --- Simple parser for FETCH responses
----------------------------------------------------------
-
-The ``imaplib`` module doesn't parse IMAP responses, it returns raw
-values. This is pretty annoying when one FETCH command is issued to
-retrieve multiple attributes of a message.
-
-This simple module tries to fix that *problem*.
-"""
-
-
-class ParseError(Exception):
- pass
-
-
-class Token(object):
-
- def __init__(self, value):
- self.value = value
-
-
-class Literal(Token):
-
- def __init__(self, value):
- super(Literal, self).__init__(value)
- self.next_token_len = int(self.value[1:-1])
-
-
-def parse_next_token(buf):
- """Look for the next *token*
-
- By *token*, I mean: *literal*, *quoted* or anything else until the
- next ' ' or ')' character (number, NIL and others should fall into
- this last category).
-
- :param buf: the buffer to parse
- :return: the position of the token's last caracter into ``buf``
- """
- end = -1
- klass = Token
- if buf[0] == '{':
- # Literal
- end = buf.find('}')
- klass = Literal
- elif buf[0] == '"':
- # quoted
- end = buf.find('"', 1)
- else:
- for pos, c in enumerate(buf):
- if c in [' ', ')']:
- end = pos - 1
- break
- if end == -1:
- raise ParseError(
- "End of buffer reached while looking for a token end")
- end += 1
- token = klass(buf[:end])
- return token, end
-
-
-def parse_bodystructure(buf, depth=0, prefix=""):
- """Special parser for BODYSTRUCTURE response
-
- This function tries to transform a BODYSTRUCTURE response sent by
- the server into the corresponding list structure.
-
- :param buf: the buffer to parse
- :return: a list object and the position of the last scanned
- character into ``buf``
- """
- ret = []
- pos = 1 # skip the first ')'
- nb_bodystruct = 0
- pnum = 1
- while pos < len(buf):
- c = buf[pos]
- if c == '(':
- nprefix = "%s.%s" % (prefix, pnum) if prefix != "" else "%s" % pnum
- subret, end = parse_bodystructure(buf[pos:], depth + 1, nprefix)
- pnum += 1
- if nb_bodystruct == 0:
- ret.append(subret)
- elif nb_bodystruct == 1:
- newret = [ret.pop(-1), subret]
- ret.append(newret)
- else:
- ret[-1].append(subret)
- pos += end + 1
- nb_bodystruct += 1
- continue
-
- if c == ')':
- partnum = None
- if depth:
- # FIXME : the following is buggy because it doesn't
- # make a difference between a content-disposition with
- # multiple args beeing parsed and a mime part! (see
- # the last example at the end of the file)
- if isinstance(ret[0], list) or len(ret) >= 7:
- partnum = prefix
- if partnum is not None:
- return [{"partnum": partnum, "struct": ret}], pos
- return ret, pos
- if c == ' ':
- pos += 1
- continue
- nb_bodystruct = 0
- token, end = parse_next_token(buf[pos:])
- pos += end
- if isinstance(token, Literal):
- ret.append(buf[pos:pos + token.next_token_len].strip('"'))
- pos += token.next_token_len
- else:
- ret.append(token.value.strip('"'))
-
- raise ParseError(
- "End of buffer reached while looking for a BODY/BODYSTRUCTURE end")
-
-
-def parse_fetch_response(data):
- """Parse a FETCH response, previously issued by a UID command
-
- We extract the message number, the UID and its value and consider
- what remains as the response data.
-
- :param data: the data returned by the ``imaplib`` command
- :return: a dictionnary
- """
- result = {}
- cpt = 0
- while cpt < len(data):
- content = ()
- while cpt < len(data) and data[cpt] != ')':
- if isinstance(data[cpt], str):
- # FIXME : probably an unsolicited response
- cpt += 1
- continue
- content += data[cpt]
- cpt += 1
- cpt += 1
-
- buf = "".join(content)
- parts = buf.split(' ', 3)
- msgdef = result[int(parts[2])] = {}
- response = parts[3]
-
- while len(response):
- if response.startswith('BODY') and response[4] == '[':
- end = response.find(']', 5)
- if response[end + 1] == '<':
- end = response.find('>', end + 1)
- end += 1
- else:
- end = response.find(' ')
- cmdname = response[:end]
- response = response[end + 1:]
-
- end = 0
- if cmdname in ['BODY', 'BODYSTRUCTURE', 'FLAGS']:
- parendepth = 0
- instring = False
- for pos, c in enumerate(response):
- if not instring and c == '"':
- instring = True
- continue
- if instring and c == '"':
- if pos and response[pos - 1] != '\\':
- instring = False
- continue
- if not instring and c == '(':
- parendepth += 1
- continue
- if not instring and c == ')':
- parendepth -= 1
- if parendepth == 0:
- end = pos + 1
- break
- else:
- token, end = parse_next_token(response)
- if isinstance(token, Literal):
- response = response[end:]
- end = token.next_token_len
-
- msgdef[cmdname] = response[:end]
- response = response[end + 1:]
- try:
- func = globals()["parse_%s" % cmdname.lower()]
- msgdef[cmdname] = func(msgdef[cmdname])[0]
- except KeyError:
- pass
-
- return result
-
-
-def dump_bodystructure(bs, depth=0):
- if depth:
- print " " * (depth * 4),
- if isinstance(bs[0], dict):
- print "%s :" % bs[0]["partnum"],
- struct = bs[0]["struct"]
- else:
- struct = bs
-
- if isinstance(struct[0], list):
- print "multipart/%s" % struct[1]
- for part in struct[0]:
- dump_bodystructure(part, depth + 1)
- else:
- print "%s/%s" % (struct[0], struct[1])
-
-
-if __name__ == "__main__":
-# resp = [('855 (UID 46931 BODYSTRUCTURE ((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 886 32 NIL NIL NIL NIL)("text" "html" ("charset" "us-ascii") NIL NIL "quoted-printable" 1208 16 NIL NIL NIL NIL) "alternative" ("boundary" "----=_NextPart_001_0003_01CCC564.B2F64FF0") NIL NIL NIL)("application" "octet-stream" ("name" "Carte Verte_2.pdf") NIL NIL "base64" 285610 NIL ("attachment" ("filename" "Carte Verte_2.pdf")) NIL NIL) "mixed" ("boundary" "----=_NextPart_000_0002_01CCC564.B2F64FF0") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {153}', 'From: \r\nTo: \r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\n\r\n'), ')']
-
-# resp = [('856 (UID 46936 BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 724 22 NIL NIL NIL NIL)("text" "html" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 2662 48 NIL NIL NIL NIL) "alternative" ("boundary" "----=_Part_1326887_254624357.1325083973970") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {258}', 'Date: Wed, 28 Dec 2011 15:52:53 +0100 (CET)\r\nFrom: =?ISO-8859-1?Q?Malakoff_M=E9d=E9ric?= \r\nTo: Antoine Nguyen \r\nSubject: =?ISO-8859-1?Q?Votre_inscription_au_grand_Jeu_Malakoff_M=E9d=E9ric?=\r\n\r\n'), ')']
-
- resp = [
- ('856 (UID 11111 BODYSTRUCTURE ((("text" "plain" ("charset" "UTF-8") NIL NIL "7bit" 0 0 NIL NIL NIL NIL) "mixed" ("boundary" "----=_Part_407172_3159001.1321948277321") NIL NIL NIL)("application" "octet-stream" ("name" "26274308.pdf") NIL NIL "base64" 14906 NIL ("attachment" ("filename" "26274308.pdf")) NIL NIL) "mixed" ("boundary" "----=_Part_407171_9686991.1321948277321") NIL NIL NIL)',
- ),
- ')']
-
-# resp = [('19 (UID 19 FLAGS (\\Seen) BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1" "format" "flowed") NIL NIL "7bit" 2 1 NIL NIL NIL NIL)("message" "rfc822" ("name*" "ISO-8859-1\'\'%5B%49%4E%53%43%52%49%50%54%49%4F%4E%5D%20%52%E9%63%E9%70%74%69%6F%6E%20%64%65%20%76%6F%74%72%65%20%64%6F%73%73%69%65%72%20%64%27%69%6E%73%63%72%69%70%74%69%6F%6E%20%46%72%65%65%20%48%61%75%74%20%44%E9%62%69%74") NIL NIL "8bit" 3632 ("Wed, 13 Dec 2006 20:30:02 +0100" {70}',
-# "[INSCRIPTION] R\xe9c\xe9ption de votre dossier d'inscription Free Haut D\xe9bit"),
-# (' (("Free Haut Debit" NIL "inscription" "freetelecom.fr")) (("Free Haut Debit" NIL "inscription" "freetelecom.fr")) ((NIL NIL "hautdebit" "freetelecom.fr")) ((NIL NIL "nguyen.antoine" "wanadoo.fr")) NIL NIL NIL "<20061213193125.9DA0919AC@dgroup2-2.proxad.net>") ("text" "plain" ("charset" "iso-8859-1") NIL NIL "8bit" 1428 38 NIL ("inline" NIL) NIL NIL) 76 NIL ("inline" ("filename*" "ISO-8859-1\'\'%5B%49%4E%53%43%52%49%50%54%49%4F%4E%5D%20%52%E9%63%E9%70%74%69%6F%6E%20%64%65%20%76%6F%74%72%65%20%64%6F%73%73%69%65%72%20%64%27%69%6E%73%63%72%69%70%74%69%6F%6E%20%46%72%65%65%20%48%61%75%74%20%44%E9%62%69%74")) NIL NIL) "mixed" ("boundary" "------------040706080908000209030901") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {266}',
-# 'Date: Tue, 19 Dec 2006 19:50:13 +0100\r\nFrom: Antoine Nguyen \r\nTo: Antoine Nguyen \r\nSubject: [Fwd: [INSCRIPTION] =?ISO-8859-1?Q?R=E9c=E9ption_de_votre_?=\r\n =?ISO-8859-1?Q?dossier_d=27inscription_Free_Haut_D=E9bit=5D?=\r\n\r\n'), ')']
-
- # resp = [('123 (UID 3 BODYSTRUCTURE (((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 1266 30 NIL NIL NIL NIL)("text" "html" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 8830 227 NIL NIL NIL NIL) "alternative" ("boundary" "_000_152AC7ECD1F8AB43A9AD95DBDDCA3118082C09GKIMA24cmcicfr_") NIL NIL NIL)("image" "png" ("name" "image005.png") "" "image005.png" "base64" 7464 NIL ("inline" ("filename" "image005.png" "size" "5453" "creation-date" "Tue, 06 Sep 2011 13:33:49 GMT" "modification-date" "Tue, 06 Sep 2011 13:33:49 GMT")) NIL NIL)("image" "jpeg" ("name" "image006.jpg") "" "image006.jpg" "base64" 2492 NIL ("inline" ("filename" "image006.jpg" "size" "1819" "creation-date" "Tue, 06 Sep 2011 13:33:49 GMT" "modification-date" "Tue, 06 Sep 2011 13:33:49 GMT")) NIL NIL) "related" ("boundary" "_006_152AC7ECD1F8AB43A9AD95DBDDCA3118082C09GKIMA24cmcicfr_" "type" "multipart/alternative") NIL NIL NIL)("application" "pdf" ("name" "bilan assurance CIC.PDF") NIL "bilan assurance CIC.PDF" "base64" 459532 NIL ("attachment" ("filename" "bilan assurance CIC.PDF" "size" "335811" "creation-date" "Fri, 16 Sep 2011 12:45:23 GMT" "modification-date" "Fri, 16 Sep 2011 12:45:23 GMT")) NIL NIL)(("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 1389 29 NIL NIL NIL NIL)("text" "html" ("charset" "utf-8") NIL NIL "quoted-printable" 1457 27 NIL NIL NIL NIL) "alternative" ("boundary" "===============0775904800==") ("inline" NIL) NIL NIL) "mixed" ("boundary" "_007_152AC7ECD1F8AB43A9AD95DBDDCA3118082C09GKIMA24cmcicfr_") NIL ("fr-FR") NIL)',), ')']
-
- # resp = [('856 (UID 11111 BODYSTRUCTURE ((("text" "plain" ("charset" "UTF-8") NIL NIL "7bit" 0 0 NIL NIL NIL NIL) "mixed" ("boundary" "----=_Part_407172_3159001.1321948277321") NIL NIL NIL)("application" "octet-stream" ("name" "26274308.pdf") NIL NIL "base64" 14906 NIL ("attachment" ("filename" "(26274308.pdf")) NIL NIL) "mixed" ("boundary" "----=_Part_407171_9686991.1321948277321") NIL NIL NIL)',), ')']
-
- print parse_fetch_response(resp)
diff --git a/modoboa/extensions/webmail/lib/imapemail.py b/modoboa/extensions/webmail/lib/imapemail.py
deleted file mode 100644
index 0b68b31e2..000000000
--- a/modoboa/extensions/webmail/lib/imapemail.py
+++ /dev/null
@@ -1,327 +0,0 @@
-"""
-Set of classes to manipulate/display emails inside the webmail.
-"""
-import os
-import re
-import email
-
-import chardet
-from rfc6266 import parse_headers
-
-from django.conf import settings
-from django.utils.translation import ugettext as _
-
-from modoboa.lib import parameters, u2u_decode
-from modoboa.lib.email_utils import Email, EmailAddress
-from .imaputils import (
- get_imapconnector, BodyStructure
-)
-from .utils import decode_payload
-
-
-class ImapEmail(Email):
-
- """
- A class to represent an email fetched from an IMAP server.
- """
-
- headernames = [
- ('From', True),
- ('To', True),
- ('Cc', True),
- ('Date', True),
- ('Subject', True),
- ]
-
- def __init__(self, request, addrfull, *args, **kwargs):
- super(ImapEmail, self).__init__(*args, **kwargs)
- self.request = request
- self.addrfull = addrfull
- self.imapc = get_imapconnector(request)
- self.mbox, self.mailid = self.mailid.split(":")
-
- headers = self.msg['BODY[HEADER.FIELDS (%s)]' % self.headers_as_text]
- msg = email.message_from_string(headers)
- for hdr in self.headernames:
- label = hdr[0]
- hdrvalue = self.get_header(msg, label)
- if not hdrvalue:
- continue
- if hdr[1]:
- self.headers += [{"name": label, "value": hdrvalue}]
- label = re.sub("-", "_", label)
- setattr(self, label, hdrvalue)
-
- def get_header(self, msg, hdrname):
- """Look for a particular header.
-
- We also try to decode the default value.
- """
- from . import imapheader
-
- hdrvalue = super(ImapEmail, self).get_header(msg, hdrname)
- if not hdrvalue:
- return ""
- try:
- key = re.sub("-", "_", hdrname).lower()
- hdrvalue = getattr(imapheader, "parse_%s" % key)(
- hdrvalue, full=self.addrfull
- )
- except AttributeError:
- pass
- return hdrvalue
-
- @property
- def msg(self):
- """
- """
- if self._msg is None:
- self._msg = self.imapc.fetchmail(
- self.mbox, self.mailid, readonly=False,
- headers=self.headers_as_list
- )
- self.bs = BodyStructure(self._msg['BODYSTRUCTURE'])
- self._find_attachments()
- if self.dformat not in ["plain", "html"]:
- self.dformat = parameters.get_user(
- self.request.user, self.dformat
- )
- fallback_fmt = "html" if self.dformat == "plain" else "plain"
- self.mformat = self.dformat \
- if self.dformat in self.bs.contents else fallback_fmt
- return self._msg
-
- @property
- def headers_as_list(self):
- return [hdr[0].upper() for hdr in self.headernames]
-
- @property
- def headers_as_text(self):
- return " ".join(self.headers_as_list)
-
- @property
- def body(self):
- """Load email's body.
-
- This operation has to be made "on demand" because it requires
- a communication with the IMAP server.
-
- """
- if self._body is None and self.bs.contents:
- bodyc = u''
- for part in self.bs.contents[self.mformat]:
- pnum = part['pnum']
- data = self.imapc._cmd(
- "FETCH", self.mailid, "(BODY.PEEK[%s])" % pnum
- )
- content = decode_payload(
- part['encoding'], data[int(self.mailid)]['BODY[%s]' % pnum]
- )
- charset = self._find_content_charset(part)
- if charset is not None:
- try:
- content = content.decode(charset)
- except (UnicodeDecodeError, LookupError):
- result = chardet.detect(content)
- content = content.decode(result['encoding'])
- bodyc += content
- self._fetch_inlines()
- self._body = getattr(self, "viewmail_%s" % self.mformat)(
- bodyc, links=self.links
- )
- return self._body
-
- @body.setter
- def body(self, value):
- self._body = value
-
- def _find_content_charset(self, part):
- for pos, elem in enumerate(part["params"]):
- if elem == "charset":
- return part["params"][pos + 1]
- return None
-
- def _find_attachments(self):
- """Retrieve attachments from the parsed body structure.
-
- We try to find and decode a file name for each attachment. If
- we failed, a generic name will be used (ie. part_1, part_2, ...).
- """
- for att in self.bs.attachments:
- attname = "part_%s" % att["pnum"]
- if "params" in att and att["params"] != "NIL":
- attname = u2u_decode.u2u_decode(att["params"][1]) \
- .strip("\r\t\n")
- elif "disposition" in att and len(att["disposition"]) > 1:
- for pos, value in enumerate(att["disposition"][1]):
- if not value.startswith("filename"):
- continue
- header = "%s; %s=%s" \
- % (att['disposition'][0],
- value,
- att["disposition"][1][pos + 1].strip("\r\t\n"))
- attname = parse_headers(header).filename_unsafe
- if attname is None:
- attname = u2u_decode.u2u_decode(
- att["disposition"][1][pos + 1]
- ).strip("\r\t\n")
- break
- self.attachments[att["pnum"]] = attname
-
- def _fetch_inlines(self):
- for cid, params in self.bs.inlines.iteritems():
- if re.search(r"\.\.", cid):
- continue
- fname = "webmail/%s_%s" % (self.mailid, cid)
- path = os.path.join(settings.MEDIA_ROOT, fname)
- params["fname"] = os.path.join(settings.MEDIA_URL, fname)
- if os.path.exists(path):
- continue
-
- pdef, content = self.imapc.fetchpart(
- self.mailid, self.mbox, params["pnum"]
- )
- with open(path, "wb") as fpo:
- fpo.write(decode_payload(params["encoding"], content))
-
- def map_cid(self, url):
- m = re.match(".*cid:(.+)", url)
- if m:
- if m.group(1) in self.bs.inlines:
- return self.bs.inlines[m.group(1)]["fname"]
- return url
-
- def render_headers(self, **kwargs):
- from django.template.loader import render_to_string
-
- res = render_to_string("webmail/headers.html", {
- "headers": self.headers,
- "folder": kwargs["folder"], "mail_id": kwargs["mail_id"],
- "attachments": self.attachments != {} and self.attachments or None
- })
- return res
-
- def fetch_attachment(self, pnum):
- """Fetch an attachment from the IMAP server.
- """
- return self.imapc.fetchpart(self.mailid, self.mbox, pnum)
-
-
-class Modifier(ImapEmail):
-
- """Message modifier."""
-
- def __init__(self, form, *args, **kwargs):
- kwargs["dformat"] = "EDITOR"
- super(Modifier, self).__init__(*args, **kwargs)
- self.form = form
- getattr(self, "_modify_%s" % self.dformat)()
-
- def _modify_plain(self):
- self.body = re.sub("?pre>", "", self.body)
-
- def _modify_html(self):
- if self.dformat == "html" and self.mformat != self.dformat:
- self.body = re.sub("?pre>", "", self.body)
- self.body = re.sub("\n", " ", self.body)
-
- @property
- def subject(self):
- """Just a shortcut to return a subject in any case."""
- return self.Subject if hasattr(self, "Subject") else ""
-
-
-class ReplyModifier(Modifier):
-
- """Modify a message to reply to it."""
-
- headernames = ImapEmail.headernames + \
- [("Reply-To", True),
- ("Message-ID", False)]
-
- def __init__(self, *args, **kwargs):
- super(ReplyModifier, self).__init__(*args, **kwargs)
-
- self.textheader = "%s %s" % (self.From, _("wrote:"))
- if hasattr(self, "Message_ID"):
- self.form.fields["origmsgid"].initial = self.Message_ID
- if not hasattr(self, "Reply_To"):
- self.form.fields["to"].initial = self.From
- else:
- self.form.fields["to"].initial = self.Reply_To
- if self.request.GET.get("all", "0") == "1": # reply-all
- self.form.fields["cc"].initial = ""
- toparse = self.To.split(",")
- if hasattr(self, 'Cc'):
- toparse += self.Cc.split(",")
- for addr in toparse:
- tmp = EmailAddress(addr)
- if tmp.address and tmp.address == self.request.user.username:
- continue
- if self.form.fields["cc"].initial != "":
- self.form.fields["cc"].initial += ", "
- self.form.fields["cc"].initial += tmp.fulladdress
- m = re.match(r"re\s*:\s*.+", self.subject.lower())
- if m:
- self.form.fields["subject"].initial = self.subject
- else:
- self.form.fields["subject"].initial = "Re: %s" % self.subject
-
- def _modify_plain(self):
- super(ReplyModifier, self)._modify_plain()
- lines = self.body.split('\n')
- body = ""
- for l in lines:
- if body != "":
- body += "\n"
- body += ">%s" % l
- self.body = body
-
-
-class ForwardModifier(Modifier):
-
- """
- Modify a message so it can be forwarded.
- """
-
- def __init__(self, *args, **kwargs):
- super(ForwardModifier, self).__init__(*args, **kwargs)
- self._header()
- self.form.fields["subject"].initial = "Fwd: %s" % self.subject
-
- def __getfunc(self, name):
- return getattr(self, "%s_%s" % (name, self.dformat))
-
- def _header(self):
- self.textheader = self.__getfunc("_header_begin")() + "\n"
- self.textheader += \
- self.__getfunc("_header_line")(_("Subject"), self.subject)
- self.textheader += \
- self.__getfunc("_header_line")(_("Date"), self.Date)
- for hdr in ["From", "To", "Reply-To"]:
- try:
- key = re.sub("-", "_", hdr)
- value = getattr(self, key)
- self.textheader += \
- self.__getfunc("_header_line")(_(hdr), value)
- except AttributeError:
- pass
- self.textheader += self.__getfunc("_header_end")()
-
- def _header_begin_plain(self):
- return "----- %s -----" % _("Original message")
-
- def _header_begin_html(self):
- return "----- %s -----" % _("Original message")
-
- def _header_line_plain(self, key, value):
- return "%s: %s\n" % (key, value)
-
- def _header_line_html(self, key, value):
- return "%s: %s
" % (key, value)
-
- def _header_end_plain(self):
- return "\n"
-
- def _header_end_html(self):
- return ""
diff --git a/modoboa/extensions/webmail/lib/imapheader.py b/modoboa/extensions/webmail/lib/imapheader.py
deleted file mode 100644
index 4d6d9628d..000000000
--- a/modoboa/extensions/webmail/lib/imapheader.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""
-Set of functions used to parse and transform email headers.
-"""
-import chardet
-from modoboa.lib.email_utils import EmailAddress
-
-__all__ = [
- 'parse_from', 'parse_to', 'parse_message_id', 'parse_date',
- 'parse_reply_to', 'parse_cc', 'parse_subject'
-]
-
-
-def to_unicode(value):
- """Try to convert a string to unicode.
- """
- if value is None or isinstance(value, unicode):
- return value
- try:
- value = value.decode('utf-8')
- except UnicodeDecodeError:
- pass
- else:
- return value
- try:
- res = chardet.detect(value)
- except UnicodeDecodeError:
- return value
- if res["encoding"] == "ascii":
- return value
- return value.decode(res["encoding"])
-
-
-def parse_address(value, **kwargs):
- """Parse an email address.
- """
- addr = EmailAddress(value)
- if "full" in kwargs.keys() and kwargs["full"]:
- return to_unicode(addr.fulladdress)
- result = addr.name and addr.name or addr.fulladdress
- return to_unicode(result)
-
-
-def parse_address_list(values, **kwargs):
- """Parse a list of email addresses.
- """
- lst = values.split(",")
- result = ""
- for addr in lst:
- if result != "":
- result += ", "
- result += parse_address(addr, **kwargs)
- return result
-
-
-def parse_from(value, **kwargs):
- """Parse a From: header.
- """
- return parse_address(value, **kwargs)
-
-
-def parse_to(value, **kwargs):
- """Parse a To: header.
- """
- return parse_address_list(value, **kwargs)
-
-
-def parse_cc(value, **kwargs):
- """Parse a Cc: header.
- """
- return parse_address_list(value, **kwargs)
-
-
-def parse_reply_to(value, **kwargs):
- """Parse a Reply-To: header.
- """
- return parse_address_list(value, **kwargs)
-
-
-def parse_date(value, **kwargs):
- """Parse a Date: header.
- """
- import datetime
- import email
-
- tmp = email.utils.parsedate_tz(value)
- if not tmp:
- return value
- try:
- ndate = datetime.datetime(*(tmp)[:7])
- now = datetime.datetime.now()
- if now - ndate > datetime.timedelta(7):
- return ndate.strftime("%d/%m/%Y %H:%M")
- return ndate.strftime("%a %H:%M")
- except ValueError:
- return value
-
-
-def parse_message_id(value, **kwargs):
- """Parse a Message-ID: header.
- """
- return value.strip('\n')
-
-
-def parse_subject(value, **kwargs):
- """Parse a Subject: header.
- """
- from modoboa.lib import u2u_decode
-
- try:
- subject = u2u_decode.u2u_decode(value)
- except UnicodeDecodeError:
- subject = value
- return to_unicode(subject)
diff --git a/modoboa/extensions/webmail/lib/imaputils.py b/modoboa/extensions/webmail/lib/imaputils.py
deleted file mode 100644
index 7d34a75c8..000000000
--- a/modoboa/extensions/webmail/lib/imaputils.py
+++ /dev/null
@@ -1,788 +0,0 @@
-# coding: utf-8
-"""
-:mod:`imaputils` --- Extra IMAPv4 utilities
--------------------------------------------
-"""
-import email
-import imaplib
-import re
-import ssl
-import time
-from functools import wraps
-
-from django.utils.translation import ugettext as _
-
-from ..exceptions import ImapError, WebmailInternalError
-from .fetch_parser import parse_fetch_response
-from modoboa.lib import parameters
-from modoboa.lib.connections import ConnectionsManager
-from modoboa.lib.exceptions import InternalError
-
-
-# imaplib.Debug = 4
-
-
-class capability(object):
-
- """
- Simple decorator to check if the server presents the required
- capability. If not, a fallback method is called instead.
-
- :param name: the capability name (upper case)
- :param fallback_method: a method's name
- """
-
- def __init__(self, name, fallback_method):
- self.name = name
- self.fallback_method = fallback_method
-
- def __call__(self, method):
- @wraps(method)
- def wrapped_func(cls, *args, **kwargs):
- if self.name in cls.capabilities:
- return method(cls, *args, **kwargs)
- return getattr(cls, self.fallback_method)(cls, **kwargs)
-
- return wrapped_func
-
-
-class BodyStructure(object):
-
- """
- BODYSTRUCTURE response parser.
-
- Just a simple class that tries to distinguish content parts from
- attachments.
- """
-
- def __init__(self, definition=None):
- self.is_multipart = False
- self.contents = {}
- self.attachments = []
- self.inlines = {}
-
- if definition is not None:
- self.load_from_definition(definition)
-
- def __store_part(self, definition, pnum, multisubtype):
- """Store the given message part in the appropriate category.
-
- This method sort parts in two categories:
-
- * contents (what is going to be displayed)
- * attachments
-
- As there is no official definition about what is a content and
- what is an attachment, the following rules are applied:
-
- * If the MIME type is text/plain or text/html:
-
- * If no previous part of this type has already been seen,
- it's a content
- * Otherwise it's an attachment
-
- * Else, if the multipart subtype is related, we consider this
- part as content because it is certainly an embedded image
-
- * Any other MIME type is considered as an attachment (for now)
-
- :param definition: a part definition (list)
- :param pnum: the part's number
- :param multisubtype: the multipart subtype
-
- """
- pnum = "1" if pnum is None else pnum
- params = dict(pnum=pnum, params=definition[2], cid=definition[3],
- description=definition[4], encoding=definition[5],
- size=definition[6])
- mtype = definition[0].lower()
- subtype = definition[1].lower()
- ftype = "%s/%s" % (definition[0].lower(), subtype)
- if ftype in ("text/plain", "text/html"):
- if subtype not in self.contents:
- self.contents[subtype] = [params]
- else:
- self.contents[subtype].append(params)
- return
- elif multisubtype in ["related"]:
- self.inlines[params["cid"].strip("<>")] = params
- return
-
- params["Content-Type"] = ftype
- if len(definition) > 7:
- extensions = ["md5", "disposition", "language", "location"]
- if mtype == "text":
- extensions = ["textlines"] + extensions
- elif ftype == "message/rfc822":
- extensions = [
- "envelopestruct",
- "bodystruct",
- "textlines"] + extensions
- for idx, value in enumerate(definition[7:]):
- params[extensions[idx]] = value
-
- self.attachments += [params]
-
- def load_from_definition(self, definition, multisubtype=None):
- if isinstance(definition, dict):
- struct = definition["struct"]
- pnum = definition["partnum"]
- elif isinstance(definition[0], dict):
- struct = definition[0]["struct"]
- pnum = definition[0]["partnum"]
- else:
- struct = definition
- pnum = None
-
- if isinstance(struct[0], list):
- for part in struct[0]:
- self.load_from_definition(part, struct[1])
- return
-
- self.__store_part(struct, pnum, multisubtype)
-
- def has_attachments(self):
- return len(self.attachments)
-
- def find_attachment(self, pnum):
- for att in self.attachments:
- if pnum == att["pnum"]:
- return att
- return None
-
-
-class IMAPconnector(object):
-
- """The IMAPv4 connector."""
-
- __metaclass__ = ConnectionsManager
-
- list_base_pattern = (
- r'\((?P.*?)\) "(?P.*)" "?(?P[^"]*)"?'
- )
- list_response_pattern_literal = re.compile(
- r'\((?P.*?)\) "(?P.*)" \{(?P\d+)\}')
- list_response_pattern = re.compile(list_base_pattern)
- listextended_response_pattern = \
- re.compile(list_base_pattern + r'\s*(?P.*)')
- unseen_pattern = re.compile(r'[^\(]+\(UNSEEN (\d+)\)')
-
- def __init__(self, user=None, password=None):
- self.__hdelimiter = None
- self.quota_usage = -1
- self.criterions = []
- self.address = parameters.get_admin("IMAP_SERVER")
- self.port = int(parameters.get_admin("IMAP_PORT"))
- self.login(user, password)
-
- def _cmd(self, name, *args, **kwargs):
- """IMAP command wrapper
-
- To simplify errors handling, this wrapper calls the
- appropriate method (``uid`` or FIXME) and then check the
- return code. If an error has occured, an ``ImapError``
- exception is raised.
-
- For specific commands commands (FETCH, ...), the result is
- parsed using the IMAPclient module before being returned.
-
- :param name: the command's name
- :return: the command's result
- """
- if name in ['FETCH', 'SORT', 'STORE', 'COPY', 'SEARCH']:
- try:
- typ, data = self.m.uid(name, *args)
- except imaplib.IMAP4.error as e:
- raise ImapError(e)
- if typ == "NO":
- raise ImapError(data)
- if name == 'FETCH':
- return parse_fetch_response(data)
- return data
-
- try:
- typ, data = self.m._simple_command(name, *args)
- except imaplib.IMAP4.error as e:
- raise ImapError(e)
- if typ == "NO":
- raise ImapError(data)
- if 'responses' not in kwargs:
- if name not in self.m.untagged_responses:
- return None
- return self.m.untagged_responses.pop(name)
- res = []
- for r in kwargs['responses']:
- if r not in self.m.untagged_responses:
- return None
- res.append(self.m.untagged_responses.pop(r))
- return res
-
- def __find_content_in_bodystruct(self, bodystruct, mtype, stype, prefix=""):
- """Retrieve the number (index) of a specific part
-
- This part number will generally be used inside a FETCH request
- to specify a ``BODY.PEEK`` section.
-
- :param bodystruct: a BODYSTRUCTURE list
- :param mtype: the MIME main type (like text)
- :param stype: the MIME sub type (like plain)
- :param prefix: the prefix that will be added to the current part number
- :return: a tuple (index (None on error), encoding (string), size (int))
- """
- if type(bodystruct[0]) in [list, tuple]:
- cpt = 1
- for part in bodystruct[0]:
- nprefix = "%s" % cpt if prefix == "" else "%s.%d" % (
- prefix, cpt)
- index, encoding, size = \
- self.__find_content_in_bodystruct(
- part,
- mtype,
- stype,
- nprefix)
- if index is not None:
- return (index, encoding, size)
- cpt += 1
- else:
- if bodystruct[0].lower() == mtype and \
- bodystruct[1].lower() == stype:
- return ("1" if not len(prefix) else prefix,
- bodystruct[5], int(bodystruct[6]))
- return (None, None, 0)
-
- @property
- def hdelimiter(self):
- """Return the default hierachy delimiter.
-
- This is a simple way to retrieve the default delimiter (see
- http://www.imapwiki.org/ClientImplementation/MailboxList).
-
- :return: a string
- """
- if self.__hdelimiter is None:
- data = self._cmd("LIST", "", "")
- m = self.list_response_pattern.match(data[0])
- if m is None:
- raise InternalError(_("Failed to retrieve hierarchy delimiter"))
- self.__hdelimiter = m.group('delimiter')
- return self.__hdelimiter
-
- def refresh(self, user, password):
- """Check if current connection needs a refresh
-
- Is it really secure?
- """
- if self.m is not None:
- try:
- self._cmd("NOOP")
- except ImapError:
- if hasattr(self, "current_mailbox"):
- del self.current_mailbox
- else:
- return
-
- self.login(user, password)
-
- def login(self, user, passwd):
- """Custom login method
-
- We connect to the server, issue a LOGIN command. If
- successfull, we try to record a eventuel CAPABILITY untagged
- response. Otherwise, we issue the command.
-
- :param user: username
- :param passwd: password
- """
- import socket
-
- if isinstance(user, unicode):
- user = user.encode("utf-8")
- if isinstance(passwd, unicode):
- passwd = passwd.encode("utf-8")
- try:
- secured = parameters.get_admin("IMAP_SECURED")
- if secured == "yes":
- self.m = imaplib.IMAP4_SSL(self.address, self.port)
- else:
- self.m = imaplib.IMAP4(self.address, self.port)
- except (socket.error, imaplib.IMAP4.error, ssl.SSLError) as error:
- raise ImapError(_("Connection to IMAP server failed: %s" % error))
-
- data = self._cmd("LOGIN", user, passwd)
- self.m.state = "AUTH"
- if "CAPABILITY" in self.m.untagged_responses:
- self.capabilities = \
- self.m.untagged_responses.pop('CAPABILITY')[0].split()
- else:
- data = self._cmd("CAPABILITY")
- self.capabilities = data[0].split()
-
- def logout(self):
- """Logout from server."""
- try:
- self._cmd("CHECK")
- except ImapError:
- pass
- self._cmd("LOGOUT")
- del self.m
- self.m = None
- if hasattr(self, "current_mailbox"):
- del self.current_mailbox
-
- def parse_search_parameters(self, criterion, pattern):
- """Parse search information and apply them."""
-
- def or_criterion(old, c):
- if old == "":
- return c
- return "OR (%s) (%s)" % (old, c)
-
- if criterion == u"both":
- criterion = u"from_addr, subject"
- criterions = ""
- if isinstance(pattern, unicode):
- pattern = pattern.encode("utf-8")
- if isinstance(criterion, unicode):
- criterion = criterion.encode("utf-8")
- for c in criterion.split(','):
- if c == "from_addr":
- key = "FROM"
- elif c == "subject":
- key = "SUBJECT"
- else:
- continue
- criterions = \
- or_criterion(criterions, '(%s "%s")' % (key, pattern))
- self.criterions = [criterions]
-
- def messages_count(self, **kwargs):
- """An enhanced version of messages_count
-
- With IMAP, to know how many messages a mailbox contains, we
- have to make a request to the server. To avoid requests
- multiplications, we sort messages in the same time. This will
- be usefull for other methods.
-
- :param order: sorting order
- :param folder: mailbox to scan
- """
- if "order" in kwargs and kwargs["order"]:
- sign = kwargs["order"][:1]
- criterion = kwargs["order"][1:].upper()
- if sign == '-':
- criterion = "REVERSE %s" % criterion
- else:
- criterion = "REVERSE DATE"
- folder = kwargs["folder"] if "folder" in kwargs else None
-
- # FIXME: pourquoi suis je obligé de faire un SELECT ici? un
- # EXAMINE plante mais je pense que c'est du à une mauvaise
- # lecture des réponses de ma part...
- self.select_mailbox(folder, readonly=False)
- data = self._cmd("SORT", "(%s)" % criterion, "UTF-8", "(NOT DELETED)",
- *self.criterions)
- self.messages = data[0].split()
- self.getquota(folder)
- return len(self.messages)
-
- def select_mailbox(self, name, readonly=True, force=False):
- """Issue a SELECT/EXAMINE command to the server
-
- The given name is first 'imap-utf7' encoded.
-
- :param name: mailbox's name
- :param readonly:
- """
- if hasattr(self, "current_mailbox"):
- if self.current_mailbox == name and not force:
- return
- self.current_mailbox = name
- name = name.encode("imap4-utf-7")
- if readonly:
- self._cmd("EXAMINE", name)
- else:
- self._cmd("SELECT", name)
- self.m.state = "SELECTED"
-
- def unseen_messages(self, mailbox):
- """Return the number of unseen messages
-
- :param mailbox: the mailbox's name
- :return: an integer
- """
- data = self._cmd("STATUS", mailbox.encode("imap4-utf-7"), "(UNSEEN)")
- m = self.unseen_pattern.match(data[-1])
- if m is None:
- return 0
- return int(m.group(1))
-
- def _encode_mbox_name(self, folder):
- if not folder:
- return "INBOX"
- return folder.encode("imap4-utf-7")
-
- def _parse_mailbox_name(self, descr, prefix, delimiter, parts):
- if not len(parts):
- return False
- path = "%s%s%s" % (prefix, delimiter, parts[0])
- sdescr = None
- for d in descr:
- if d["path"] == path:
- sdescr = d
- break
- if sdescr is None:
- sdescr = {"name": parts[0], "path": path, "sub": []}
- descr += [sdescr]
- if self._parse_mailbox_name(sdescr["sub"], path, delimiter, parts[1:]):
- sdescr["class"] = "subfolders"
- return True
-
- def _listmboxes_simple(self, topmailbox='INBOX', mailboxes=None, **kwargs):
- # data = self._cmd("LIST", "", "*")
- if not mailboxes:
- mailboxes = []
- (status, data) = self.m.list()
- newmboxes = []
- for mb in data:
- flags, delimiter, name = self.list_response_pattern.match(
- mb).groups()
- name = name.strip('"').decode("imap4-utf-7")
- mdm_found = False
- for idx, mdm in enumerate(mailboxes):
- if mdm["name"] == name:
- mdm_found = True
- descr = mailboxes[idx]
- break
- if not mdm_found:
- descr = dict(name=name)
- newmboxes += [descr]
-
- if re.search("\%s" % delimiter, name):
- parts = name.split(delimiter)
- if "path" not in descr:
- descr["path"] = parts[0]
- descr["sub"] = []
- if self._parse_mailbox_name(descr["sub"], parts[0], delimiter,
- parts[1:]):
- descr["class"] = "subfolders"
- continue
-
- from operator import itemgetter
- mailboxes += sorted(newmboxes, key=itemgetter("name"))
-
- @capability('LIST-EXTENDED', '_listmboxes_simple')
- def _listmboxes(self, topmailbox, mailboxes, until_mailbox=None):
- """Retrieve mailboxes list."""
- pattern = (
- "{0}{1}%".format(topmailbox.encode("imap4-utf-7"), self.hdelimiter)
- if topmailbox else "%"
- )
- resp = self._cmd("LIST", "", pattern, "RETURN", "(CHILDREN)")
- newmboxes = []
- for mb in resp:
- if not mb:
- continue
- if type(mb) in [str, unicode]:
- flags, delimiter, name, childinfo = \
- self.listextended_response_pattern.match(mb).groups()
- else:
- flags, delimiter, namelen = (
- self.list_response_pattern_literal.match(mb[0]).groups()
- )
- name = mb[1][0:int(namelen)]
- flags = flags.split(' ')
- name = name.decode("imap4-utf-7")
- mdm_found = False
- for idx, mdm in enumerate(mailboxes):
- if mdm["name"] == name:
- mdm_found = True
- descr = mailboxes[idx]
- break
- if not mdm_found:
- descr = dict(name=name)
- newmboxes += [descr]
-
- if r'\Marked' in flags or r'\UnMarked' not in flags:
- descr["send_status"] = True
- if r'\HasChildren' in flags:
- if r'\NonExistent' in flags:
- descr["removed"] = True
- descr["path"] = name
- descr["sub"] = []
- if until_mailbox and until_mailbox.startswith(name):
- self._listmboxes(name, descr["sub"], until_mailbox)
-
- from operator import itemgetter
- mailboxes += sorted(newmboxes, key=itemgetter("name"))
-
- def getmboxes(
- self, user, topmailbox='', until_mailbox=None,
- unseen_messages=True):
- """Returns a list of mailboxes for a particular user
-
- By default, only the first level of mailboxes under
- ``topmailbox`` is returned. If ``until_mailbox`` is specified,
- all levels needed to access this mailbox will be returned.
-
- :param user: a ``User`` instance
- :param topmailbox: the mailbox where to start in the tree
- :param until_mailbox: the deepest needed mailbox
- :param unseen_messages: include unseen messages counters or not
- :return: a list
- """
- if topmailbox:
- md_mailboxes = []
- else:
- md_mailboxes = [
- {"name": "INBOX", "class": "fa fa-inbox"},
- {"name": parameters.get_user(user, "DRAFTS_FOLDER"),
- "class": "fa fa-file"},
- {"name": 'Junk', "class": "fa fa-fire"},
- {"name": parameters.get_user(user, "SENT_FOLDER"),
- "class": "fa fa-envelope"},
- {"name": parameters.get_user(user, "TRASH_FOLDER"),
- "class": "fa fa-trash"}
- ]
- if until_mailbox:
- name, parent = separate_mailbox(until_mailbox, self.hdelimiter)
- if parent:
- until_mailbox = parent
- self._listmboxes(topmailbox, md_mailboxes, until_mailbox)
-
- if unseen_messages:
- for mb in md_mailboxes:
- if "send_status" not in mb:
- continue
- del mb["send_status"]
- key = "path" if "path" in mb else "name"
- if not mb.get("removed", False):
- count = self.unseen_messages(mb[key])
- if count == 0:
- continue
- mb["unseen"] = count
- return md_mailboxes
-
- def _add_flag(self, mbox, msgset, flag):
- """Add flag(s) to a messages set
-
- :param mbox: the mailbox containing the messages
- :param msgset: messages set (uid)
- :param flag: the flag to add
- """
- self.select_mailbox(mbox, False)
- self._cmd("STORE", msgset, "+FLAGS", flag)
-
- def mark_messages_unread(self, mbox, msgset):
- """Mark a set of messages as unread
-
- :param mbox: the mailbox containing the messages
- :param msgset: messages set (uid)
- """
- self.select_mailbox(mbox, False)
- self._cmd("STORE", msgset, "-FLAGS", r'(\Seen)')
-
- def mark_messages_read(self, mbox, msgset):
- """Mark a set of messages as unread
-
- :param mbox: the mailbox containing the messages
- :param msgset: messages set (uid)
- """
- self._add_flag(mbox, msgset, r'(\Seen)')
-
- def msg_forwarded(self, mailbox, mailid):
- self._add_flag(mailbox, mailid, '($Forwarded)')
-
- def msg_answered(self, mailbox, mailid):
- """Add the \Answered flag to this email"""
- self._add_flag(mailbox, mailid, r'(\Answered)')
-
- def move(self, msgset, oldmailbox, newmailbox):
- """Move messages between mailboxes
-
- """
- self.select_mailbox(oldmailbox, False)
- self._cmd("COPY", msgset, newmailbox.encode("imap4-utf-7"))
- self._cmd("STORE", msgset, "+FLAGS", r'(\Deleted \Seen)')
-
- def push_mail(self, folder, msg):
- now = imaplib.Time2Internaldate(time.time())
- self.m.append(self._encode_mbox_name(folder), r'(\Seen)', now, str(msg))
-
- def empty(self, mbox):
- self.select_mailbox(mbox, False)
- resp = self._cmd("SEARCH", "ALL")
- seq = ",".join(resp[0].split())
- if seq == "":
- return
- self._cmd("STORE", seq, "+FLAGS", r'(\Deleted)')
- self._cmd("EXPUNGE")
-
- def compact(self, mbox):
- """Compact a specific mailbox
-
- Issue an EXPUNGE command for the specified mailbox.
-
- :param mbox: the mailbox's name
- """
- self.select_mailbox(mbox, False)
- self._cmd("EXPUNGE")
-
- def create_folder(self, name, parent=None):
- if parent is not None:
- name = "%s%s%s" % (parent, self.hdelimiter, name)
- typ, data = self.m.create(self._encode_mbox_name(name))
- if typ == "NO":
- raise WebmailInternalError(data[0])
- return True
-
- def rename_folder(self, oldname, newname):
- typ, data = self.m.rename(self._encode_mbox_name(oldname),
- self._encode_mbox_name(newname))
- if typ == "NO":
- raise WebmailInternalError(data[0], ajax=True)
- return True
-
- def delete_folder(self, name):
- typ, data = self.m.delete(self._encode_mbox_name(name))
- if typ == "NO":
- raise WebmailInternalError(data[0])
- return True
-
- def getquota(self, mailbox):
- """Retrieve quota information from the server.
-
- We also compute the current usage.
- """
- if "QUOTA" not in self.capabilities:
- self.quota_limit = self.quota_current = None
- return
-
- data = self._cmd("GETQUOTAROOT", self._encode_mbox_name(mailbox),
- responses=["QUOTAROOT", "QUOTA"])
- if data is None:
- self.quota_limit = self.quota_current = None
- return
-
- quotadef = data[1][0]
- m = re.search(r"\(STORAGE (\d+) (\d+)\)", quotadef)
- if not m:
- print "Problem while parsing quota def"
- return
- self.quota_limit = int(m.group(2))
- self.quota_current = int(m.group(1))
- try:
- self.quota_usage = (
- int(float(self.quota_current) / float(self.quota_limit) * 100)
- )
- except TypeError:
- self.quota_usage = -1
-
- def fetchpart(self, uid, mbox, partnum):
- """Retrieve a specific message part
-
- Useful to fetch attachments from the server. Part headers and
- the payload are returned separatly.
-
- :param uid: a message UID
- :param mbox: the mailbox containing the message
- :param partnum: the part number
- :return: a 2uple (dict, string)
- """
- self.select_mailbox(mbox, False)
- data = self._cmd("FETCH", uid, "(BODYSTRUCTURE BODY[%s])" % partnum)
- bs = BodyStructure(data[int(uid)]["BODYSTRUCTURE"])
- attdef = bs.find_attachment(partnum)
- return attdef, data[int(uid)]["BODY[%s]" % partnum]
-
- def fetch(self, start, stop=None, mbox=None):
- """Retrieve information about messages from the server
-
- Issue a FETCH command to retrieve information about one or
- more messages (such as headers) from the server.
-
- :param start: index of the first message
- :param stop: index of the last message (optionnal)
- :param mbox: the mailbox that contains the messages
- """
- self.select_mailbox(mbox, False)
- if start and stop:
- submessages = self.messages[start - 1:stop]
- mrange = ",".join(submessages)
- else:
- submessages = [start]
- mrange = start
- query = (
- "(FLAGS BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (DATE FROM TO CC "
- "SUBJECT)])"
- )
- data = self._cmd("FETCH", mrange, query)
- result = []
- for uid in submessages:
- msg = email.message_from_string(
- data[int(uid)]['BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)]']
- )
- msg['imapid'] = uid
- if r'\Seen' not in data[int(uid)]['FLAGS']:
- msg['style'] = 'unseen'
- if r'\Answered' in data[int(uid)]['FLAGS']:
- msg['answered'] = True
- if r'$Forwarded' in data[int(uid)]['FLAGS']:
- msg['forwarded'] = True
- bstruct = BodyStructure(data[int(uid)]['BODYSTRUCTURE'])
- if bstruct.has_attachments():
- msg['attachments'] = True
- result += [msg]
- return result
-
- def fetchmail(self, mbox, mailid, readonly=True, headers=None):
- """Retrieve information about a specific message
-
- Issue a FETCH command to retrieve a message's content from the
- server. In order to not overload the server, we first retrieve
- the BODYSTRUCTURE of the message. Then, according to the
- result and to the user's preferences, we retrieve the
- appropriate content (plain, html, etc.).
-
- :param mbox: the mailbox containing the message
- :param mailid: the message's unique id
- :param readonly:
- :param headers:
- """
- self.select_mailbox(mbox, readonly)
- if headers is None:
- headers = ['DATE', 'FROM', 'TO', 'CC', 'SUBJECT']
- bcmd = "BODY.PEEK" if readonly else "BODY"
- data = self._cmd(
- "FETCH", mailid,
- "(BODYSTRUCTURE %s[HEADER.FIELDS (%s)])" % (bcmd, " ".join(headers))
- )
- return data[int(mailid)]
-
-
-def separate_mailbox(fullname, sep="."):
- """Split a mailbox name
-
- If a separator is found in ``fullname``, this function returns the
- corresponding name and parent mailbox name.
- """
- if sep in fullname:
- parts = fullname.split(sep)
- name = parts[-1]
- parent = sep.join(parts[0:len(parts) - 1])
- return name, parent
- return fullname, None
-
-
-def get_imapconnector(request):
- """Simple shortcut to create a connector
-
- :param request: a ``Request`` object
- """
- imapc = IMAPconnector(user=request.user.username,
- password=request.session["password"])
- return imapc
-
-
-if __name__ == "__main__":
- import doctest
- doctest.testmod()
diff --git a/modoboa/extensions/webmail/lib/sendmail.py b/modoboa/extensions/webmail/lib/sendmail.py
deleted file mode 100644
index 14b4eaa19..000000000
--- a/modoboa/extensions/webmail/lib/sendmail.py
+++ /dev/null
@@ -1,65 +0,0 @@
-import smtplib
-from modoboa.lib import parameters
-from modoboa.lib.email_utils import prepare_addresses
-from modoboa.lib.web_utils import _render_to_string
-from modoboa.lib.cryptutils import get_password
-from modoboa.extensions.webmail.exceptions import WebmailInternalError
-from . import get_imapconnector, clean_attachments
-
-
-def send_mail(request, form, posturl=None):
- """Email verification and sending.
-
- If the form does not present any error, a new MIME message is
- constructed. Then, a connection is established with the defined
- SMTP server and the message is finally sent.
-
- :param request: a Request object
- :param posturl: the url to post the message form to
- :return: a 2-uple (True|False, HttpResponse)
- """
- if not form.is_valid():
- editormode = parameters.get_user(request.user, "EDITOR")
- listing = _render_to_string(
- request, "webmail/compose.html",
- {"form": form, "noerrors": True,
- "body": form.cleaned_data.get("body", "").strip(),
- "posturl": posturl}
- )
- return False, dict(status="ko", listing=listing, editor=editormode)
-
- msg = form.to_msg(request)
- rcpts = prepare_addresses(form.cleaned_data["to"], "envelope")
- for hdr in ["cc", "cci"]:
- if form.cleaned_data[hdr]:
- msg[hdr.capitalize()] = prepare_addresses(form.cleaned_data[hdr])
- rcpts += prepare_addresses(form.cleaned_data[hdr], "envelope")
- try:
- secmode = parameters.get_admin("SMTP_SECURED_MODE")
- if secmode == "ssl":
- s = smtplib.SMTP_SSL(parameters.get_admin("SMTP_SERVER"),
- int(parameters.get_admin("SMTP_PORT")))
- else:
- s = smtplib.SMTP(parameters.get_admin("SMTP_SERVER"),
- int(parameters.get_admin("SMTP_PORT")))
- if secmode == "starttls":
- s.starttls()
- except Exception as text:
- raise WebmailInternalError(str(text))
-
- if parameters.get_admin("SMTP_AUTHENTICATION") == "yes":
- try:
- s.login(request.user.username, get_password(request))
- except smtplib.SMTPException as err:
- raise WebmailInternalError(str(err))
- try:
- s.sendmail(request.user.email, rcpts, msg.as_string())
- s.quit()
- except smtplib.SMTPException as err:
- raise WebmailInternalError(str(err))
-
- sentfolder = parameters.get_user(request.user, "SENT_FOLDER")
- get_imapconnector(request).push_mail(sentfolder, msg)
- clean_attachments(request.session["compose_mail"]["attachments"])
- del request.session["compose_mail"]
- return True, {}
diff --git a/modoboa/extensions/webmail/lib/signature.py b/modoboa/extensions/webmail/lib/signature.py
deleted file mode 100644
index 2b24507fa..000000000
--- a/modoboa/extensions/webmail/lib/signature.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import re
-from modoboa.lib import parameters
-
-
-class EmailSignature(object):
-
- """User signature
-
- :param user: User object
- """
-
- def __init__(self, user):
- self._sig = u""
- dformat = parameters.get_user(user, "EDITOR")
- content = parameters.get_user(user, "SIGNATURE")
- if len(content):
- getattr(self, "_format_sig_%s" % dformat)(content)
-
- def _format_sig_plain(self, content):
- self._sig = u"""
----
-%s""" % content
-
- def _format_sig_html(self, content):
- content = re.sub("\n", " ", content)
- self._sig = u"""
----
-%s""" % content
-
- def __unicode__(self):
- return self._sig
diff --git a/modoboa/extensions/webmail/lib/utils.py b/modoboa/extensions/webmail/lib/utils.py
deleted file mode 100644
index 366384de0..000000000
--- a/modoboa/extensions/webmail/lib/utils.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-Misc. utilities.
-"""
-from modoboa.lib.web_utils import NavigationParameters
-
-
-def decode_payload(encoding, payload):
- """Decode the payload according to the given encoding
-
- Supported encodings: base64, quoted-printable.
-
- :param encoding: the encoding's name
- :param payload: the value to decode
- :return: a string
- """
- encoding = encoding.lower()
- if encoding == "base64":
- import base64
- return base64.b64decode(payload)
- elif encoding == "quoted-printable":
- import quopri
- return quopri.decodestring(payload)
- return payload
-
-
-class WebmailNavigationParameters(NavigationParameters):
-
- """
- Specific NavigationParameters subclass for the webmail.
- """
-
- def __init__(self, request, defmailbox=None):
- super(WebmailNavigationParameters, self).__init__(
- request, 'webmail_navparams'
- )
- if defmailbox is not None:
- self.parameters += [('mbox', defmailbox, False)]
-
- def _store_page(self):
- """Specific method to store the current page."""
- if self.request.GET.get("reset_page", None) or "page" not in self:
- self["page"] = 1
- else:
- page = self.request.GET.get("page", None)
- if page is not None:
- self["page"] = int(page)
diff --git a/modoboa/extensions/webmail/modo_extension.py b/modoboa/extensions/webmail/modo_extension.py
deleted file mode 100644
index 7ee635a15..000000000
--- a/modoboa/extensions/webmail/modo_extension.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# coding: utf-8
-"""Declare and register the webmail extension."""
-
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.lib import parameters
-
-
-class Webmail(ModoExtension):
- name = "webmail"
- label = "Webmail"
- version = "1.0"
- description = ugettext_lazy("Simple IMAP webmail")
- needs_media = True
- available_for_topredirection = True
-
- def load(self):
- from .app_settings import ParametersForm, UserSettings
-
- parameters.register(ParametersForm, "Webmail")
- parameters.register(UserSettings, "Webmail")
- from modoboa.extensions.webmail import general_callbacks
-
-exts_pool.register_extension(Webmail)
diff --git a/modoboa/extensions/webmail/static/webmail/css/attachments.css b/modoboa/extensions/webmail/static/webmail/css/attachments.css
deleted file mode 100644
index b4c0de430..000000000
--- a/modoboa/extensions/webmail/static/webmail/css/attachments.css
+++ /dev/null
@@ -1,40 +0,0 @@
-#attachment_list {
- border: 1px solid #ccc;
- background-color: #eee;
- position: absolute;
- top: 140px;
- left: 20px;
- right: 20px;
- bottom: 35px;
- overflow-x: hidden;
- overflow-y: auto;
- padding: 2px;
-}
-
-#upload_status {
- position: relative;
- margin: 0 auto;
- font-size: 0.9em;
- width: 120px;
- font-style: italic;
-}
-
-#done_container {
- position: absolute;
- bottom: 0;
- width: 100%;
- text-align: center;
-}
-
-img {
- float: left;
- margin-right: 5px;
-}
-
-div.row label {
- width: 150px;
-}
-
-#id_attachment {
- width: 290px;
-}
diff --git a/modoboa/extensions/webmail/static/webmail/css/webmail.css b/modoboa/extensions/webmail/static/webmail/css/webmail.css
deleted file mode 100644
index 4e73a4381..000000000
--- a/modoboa/extensions/webmail/static/webmail/css/webmail.css
+++ /dev/null
@@ -1,303 +0,0 @@
-/* MEDIA */
-
-@media (min-width: 768px) {
- .main {
- padding-left: 0;
- padding-right: 0;
- }
-}
-
-@media (max-width: 1198px) {
- .container-fluid {
- padding: 0;
- }
-
- .display-up-1198-webmail {
- display: none;
- }
- .display-less-1198{
- display: inherit;
- }
-
-}
-
-/* GENERAL */
-
-.main {
- position: absolute;
- top: 51px;
- left: 0;
- right: 0;
- bottom: 0;
- overflow-x: hidden;
-}
-
-#listing {
- position: absolute;
- top: 75px;
- bottom: 0;
- left: 0;
- right: 0;
- overflow-y: auto;
- overflow-x: hidden;
- padding-left: 15px;
- padding-right: 15px;
-}
-
-#folders {
- top: 73px;
- left: 15px;
- right: 15px;
- overflow-x: auto;
- overflow-y: auto;
-}
-
-/* .sidebar .ui-resizable-handle { */
-/* background-position: center center; */
-/* background-repeat: no-repeat; */
-/* } */
-
-/* .sidebar .ui-resizable-n { */
-/* top: 0px; */
-/* } */
-
-/* .sidebar .ui-resizable-s { */
-/* bottom: 0px; */
-/* } */
-
-/* .sidebar .ui-resizable-e { */
-/* right: 0px; */
-/* background-image: url("../../pics/grippy.png"); */
-/* width: 8px; */
-/* } */
-
-/* .sidebar .ui-resizable-w { */
-/* left: 0px; */
-/* background-image: url("../../pics/grippy.png"); */
-/* width: 8px; */
-/* } */
-
-.nav-sidebar li > a {
- padding-top: 7px;
- padding-bottom: 7px;
-}
-
-.nav-sidebar li li {
- padding-left: 10px;
-}
-
-#mboxes_container a[name=loadfolder] {
- white-space: nowrap;
- overflow: auto;
- text-overflow: ellipsis;
- -o-text-overflow: ellipsis;
-}
-
-#mailcontent {
- border: 0;
- margin: 0;
- padding: 0;
- width: 100%;
- height: 100%;
-}
-
-.unseen {
- font-weight: bold;
-}
-
-#left-toolbar {
- position: absolute;
- margin-left: 0px;
- width: 100%;
- left: 0;
- bottom: 0;
-}
-
-#quotabox {
- padding-top: 15px;
-}
-
-#quotabar {
- height: 5px;
- margin-bottom: 0;
-}
-
-#quotaraw {
- margin-left: 10px;
-}
-
-
-/*
- * Mailboxes list
- */
-.email {
- border-top: 1px solid #ddd;
- padding-top: 10px;
-}
-
-div.email:hover {
- background-color: #f5f5f5;
-}
-
-.openable {
- cursor: pointer;
-}
-
-.leftcol-heading {
- margin-bottom: 15px;
-}
-
-#mboxactions {
- margin: 5px 0;
-}
-
-div.clickbox {
- position: absolute;
- left: 10px;
- top: 5px;
- width: 14px;
- height: 14px;
- z-index: 100;
-}
-
-div.collapsed {
- background-image: url("../../pics/collapsed.png");
- background-repeat: no-repeat;
-}
-
-div.expanded {
- background-image: url("../../pics/expanded.png");
- background-repeat: no-repeat;
-}
-
-#mboxes_container .nav .droppable div.clickbox {
- z-index: 800;
-}
-
-/*
- * Compose form
- */
-#mailheader {
- position: relative;
- padding-bottom: 5px;
-}
-
-#mailheader label {
- text-align: left;
-}
-
-#mailheader .options {
- margin-bottom: 8px;
-}
-
-#attachments {
- position: relative;
- margin: 1px 0 5px 0;
- padding: 5px 0;
- cursor: pointer;
- width: 100%;
-}
-
-#attachments img {
- float: left;
-}
-
-list {
- position: absolute;
- top: 5px;
- left: 180px;
- font-weight: bold;
-}
-
-#body_container {
- position: static;
- /*height: 600px;*/
-}
-
-#id_body {
- width: 100%;
- height: 100%;
-}
-
-/*
- * Attachments form
- */
-#submit {
- margin: 0 auto;
-}
-
-#attachment_list {
- margin-top: 20px;
- height: 150px;
- overflow-x: hidden;
- overflow-y: auto;
- padding: 2px;
-}
-
-#attachment_list i,
-#attachment_list label {
- float: left;
-}
-
-/*
- * Drap & Drop
- */
-.dragbox {
- padding : 5px;
- text-align : center;
- z-index : 1001;
-}
-
-/*
- * Folders form
- */
-
-.modal-body {
- max-height: 300px;
- overflow-y: auto;
-}
-
-#folders2 li {
- position: relative;
-}
-
-#folders2 div.clickbox {
- left: 0;
- top: 0px;
-}
-
-#folders2 li li {
- margin-left: 10px;
-}
-
-#folders2 .active > a,
-#folders2 .active > a:hover,
-#folders2 .active > a:focus {
- color: #fff;
- background-color: #428bca;
-}
-
-/*
- * Table
- */
-
-
-
-/*
- * Action buttons
- */
-
-#menubar {
- padding-left: 15px;
- padding-bottom: 20px;
- z-index: 100;
-}
-
-#menubar .btn-toolbar ul.navbar-right{
- margin-right: 3%;
-}
-
-#menubar .btn-toolbar .navbar-form{
- margin: 0px;
-}
-
diff --git a/modoboa/extensions/webmail/static/webmail/js/webmail.js b/modoboa/extensions/webmail/static/webmail/js/webmail.js
deleted file mode 100644
index f34a39365..000000000
--- a/modoboa/extensions/webmail/static/webmail/js/webmail.js
+++ /dev/null
@@ -1,1285 +0,0 @@
-/**
- * Creates an instance of Webmail.
- *
- * @constructor
- * @param {Object} options - instance options
- * @classdesc The javascript code that brings the webmail to life!
- */
-var Webmail = function(options) {
- this.initialize(options);
-};
-
-Webmail.prototype = {
- constructor: Webmail,
-
- defaults: {
- poller_interval: 300, /* in seconds */
- poller_url: "",
- move_url: "",
- submboxes_url: "",
- delattachment_url: "",
- ro_mboxes: ["INBOX"],
- trash: "",
- hdelimiter: '.',
- mboxes_col_width: 200
- },
-
- initialize: function(options) {
- this.options = $.extend({}, this.defaults, options);
- this.rtimer = null;
- this.editorid = "id_body";
-
- this.navobject = new History({
- deflocation: "?action=listmailbox&reset_page=true",
- defcallback: $.proxy(this.listmailbox_callback, this)
- });
- this.poller = new Poller(this.options.poller_url, {
- interval: this.options.poller_interval * 1000,
- success_cb: $.proxy(this.poller_cb, this),
- args: this.get_visible_mailboxes
- });
- this.record_unseen_messages();
-
- $("#mboxactions").on("shown.bs.dropdown", function() {
- var $menu = $("ul", this);
- var offset = $menu.offset();
-
- $("body").append($menu);
- $menu.show();
- $menu.css("position", "absolute");
- $menu.css("top", offset.top + "px");
- $menu.css("left", offset.left + "px");
- $(this).data("original_menu", $menu);
- }).on("hide.bs.dropdown", function() {
- var $this = $(this);
- $this.append($this.data("original_menu"));
- $this.data("original_menu").removeAttr("style");
- });
-
- $(".sidebar").resizable({
- start: function(event, ui) {
- $('#listing iframe').css('pointer-events', 'none');
- },
- handles: "e",
- minWidth: $(".sidebar").width(),
- maxWidth: 400,
- stop: function(event, ui) {
- $('#listing iframe').css('pointer-events', 'auto');
- },
- resize: function(event, ui) {
- $(".main").css({
- marginLeft: ui.size.width + "px"
- });
- }
- });
-
- this.resize();
-
- this.init_droppables();
- this.register_navcallbacks();
- this.listen();
- },
-
- /**
- * Register navigation callbacks.
- *
- * @this Webmail
- */
- register_navcallbacks: function() {
- this.navobject.register_callback(
- "listmailbox", $.proxy(this.listmailbox_callback, this));
- this.navobject.register_callback(
- "compose", $.proxy(this.compose_callback, this));
- this.navobject.register_callback(
- "viewmail", $.proxy(this.viewmail_callback, this));
-
- this.navobject.register_callback(
- "reply", $.proxy(this.compose_callback, this));
- this.navobject.register_callback(
- "replyall", $.proxy(this.compose_callback, this));
- this.navobject.register_callback(
- "forward", $.proxy(this.compose_callback, this));
- },
-
- listen: function() {
- $(window).resize($.proxy(this.resize, this));
-
- $(document).on(
- "click", "a[name=compose]", $.proxy(this.compose_loader, this));
- $(document).on(
- "click", "a[name=totrash]", $.proxy(this.delete_messages, this));
- $(document).on(
- "click", "a[name*=mark-]", $.proxy(this.send_mark_request, this));
- $(document).on("click", "a[name=compress]", $.proxy(this.compress, this));
- $(document).on("click", "a[name=empty]", $.proxy(this.empty, this));
- $(document).on("click", "#bottom-bar a", $.proxy(this.getpage_loader, this));
-
- $(document).on(
- "click", "a[name=loadfolder]", $.proxy(this.listmailbox_loader, this));
- $(document).on("click", "a[name=selectfolder]", this.select_parent_mailbox);
- $(document).on(
- "click", "div[class*=clickbox]", $.proxy(this.mbox_state_callback, this));
- $(document).on("click", "a[name=newmbox]", $.proxy(this.new_mailbox, this));
- $(document).on("click", "a[name=editmbox]", $.proxy(this.edit_mbox, this));
- $(document).on("click", "a[name=removembox]", $.proxy(this.remove_mbox, this));
-
- $(document).on("click", "div.openable", $.proxy(this.viewmail_loader, this));
-
- $(document).on("click", "a[name=reply]", $.proxy(this.reply_loader, this));
- $(document).on("click", "a[name=replyall]", $.proxy(this.reply_loader, this));
- $(document).on("click", "a[name=forward]", $.proxy(this.reply_loader, this));
- $(document).on("click", "a[name=delete]", $.proxy(this.delete_message, this));
- $(document).on(
- "click", "a[name=activate_links]", $.proxy(function(e) { this.display_mode(e, "1"); }, this));
- $(document).on("click", "a[name=disable_links]", $.proxy(function(e) { this.display_mode(e, "0"); }, this));
-
- $(document).on("click", "a[name=sendmail]", $.proxy(this.sendmail, this));
-
- $(document).on("click", "a[name=attachments]", $.proxy(function(e) {
- modalbox(e, undefined, $("a[name=attachments]").attr("href"),
- $.proxy(this.attachments_init, this));
- }, this));
- },
-
- /**
- * Setup an "infinite scroll" behaviour for the email list.
- */
- setup_infinite_scroll: function(data) {
- var $container = $("#listing");
- var that = this;
-
- if ($container.data("infinite-scroll") !== undefined) {
- if (data.pages && data.pages[0] != 1) {
- $container.scrollTop(10);
- }
- $container.infinite_scroll("reset_loaded_pages", data.pages);
- $container.infinite_scroll("resume");
- return;
- }
-
- $container.infinite_scroll({
- initial_pages: data.pages,
- url: this.options.listing_url,
- calculate_bottom: function($element) {
- return $("#emails").height() - $element.height();
- },
- get_args: function() {
- var args = $.extend({}, that.navparams);
- args.scroll = true;
- return args;
- },
- process_results: function(data, direction) {
- var $emails = $("#emails");
-
- if (direction === "down") {
- $emails.html($emails.html() + data.listing);
- } else {
- var row_id = $emails.children(".email").first().attr("id");
-
- $emails.html(data.listing + $emails.html());
-
- var $row = $("#" + row_id);
- $("#listing").scrollTop($row.offset().top);
- }
- },
- end_of_list_reached: function($element) {
- $element.append(
- $("
").html(
- gettext("No more message in this mailbox.")
- )
- );
- }
- });
- },
-
- /**
- * Disable the infinite scroll mode.
- */
- disable_infinite_scroll: function() {
- var $container = $("#listing");
-
- if ($container.data("infinite-scroll") !== undefined) {
- $container.infinite_scroll("pause");
- }
- },
-
- record_unseen_messages: function() {
- var unseen_counters = {};
-
- $("#folders").find("a.unseen").each(function() {
- var $this = $(this);
- unseen_counters[$this.attr("href")] = parseInt($this.attr("data-toggle"));
- });
- this.unseen_counters = unseen_counters;
- },
-
- /**
- * Global resize event callback.
- */
- resize: function() {
- var $window = $(window);
- var current_action = this.navobject.getparam("action");
-
- $("#folders").height(
- $("#left-toolbar").offset().top - $("#folders").offset().top
- );
-
- // if ($window.width() <= 768) {
- // $(".main").css("margin-left", "0");
- // } else {
- // $(".main").css("margin-left", $(".sidebar").width() + "px");
- // }
- if (current_action == "compose") {
- this.resize_compose_body();
- }
- },
-
- /**
- * Resize the textarea used to write plain/text messages.
- */
- resize_compose_body: function() {
- var $container = $("#body_container");
-
- if ($container.length) {
- var top = $container.offset().top;
-
- $("#body_container").innerHeight($(window).height() - top - 10);
- }
- },
-
- /**
- * Callback of the 'compose' action.
- *
- * It is also shared with other similar actions : reply, forward.
- */
- resize_editor: function() {
- CKEDITOR.instances[this.editorid].resize("100%",
- $("#body_container").outerHeight(true));
- },
-
- /**
- * Simple helper to retrieve the currently selected mailbox.
- *
- * @this Webmail
- */
- get_current_mailbox: function() {
- return this.navobject.getparam("mbox", "INBOX");
- },
-
- /**
- * Keep track of interesting navigation parameters in order to
- * restore them later.
- *
- * @this Webmail
- */
- store_nav_params: function() {
- var params = new Array("order", "pattern", "criteria");
-
- this.navparams = {};
- for (var idx in params) {
- this.navparams[params[idx]] = this.navobject.getparam(params[idx]);
- }
- },
-
- /**
- * Restore navigation parameters previously stored via
- * store_nav_params.
- *
- * @this Webmail
- */
- restore_nav_params: function() {
- if (this.navparams === undefined) {
- return;
- }
- var navobject = this.navobject;
- $.each(this.navparams, function(key, value) {
- if (value === undefined) {
- return;
- }
- navobject.setparam(key, value);
- });
- },
-
- go_back_to_listing: function() {
- var curmb = this.get_current_mailbox();
- this.navobject.reset()
- .setparams({action: "listmailbox", mbox: curmb});
- this.restore_nav_params();
- this.navobject.update(true);
- },
-
- /*
- * Enable or disable edit and remove actions for the currently
- * selected mailbox.
- */
- enable_mb_actions: function(state) {
- if (state === undefined) {
- state = true;
- }
- if (state) {
- $("a[name=editmbox], a[name=removembox]").removeClass("disabled");
- } else {
- $("a[name=editmbox], a[name=removembox]").addClass("disabled");
- }
- },
-
- /**
- * Update the current displayed content.
- *
- * @this Webmail
- * @param {Object} response - object containing the new content
- */
- page_update: function(response) {
- var curmb = this.get_current_mailbox();
-
- if (!$('li[name="' + curmb + '"]').hasClass("active")) {
- this.load_and_select_mailbox(curmb);
- }
- this.enable_mb_actions();
- for (var idx in this.options.ro_mboxes) {
- if (curmb == this.options.ro_mboxes[idx]) {
- this.enable_mb_actions(false);
- break;
- }
- }
- if (response.menu !== undefined) {
- $("#menubar").html(response.menu);
- $("#searchfield").searchbar({
- navobj: this.navobject,
- pattern_changed: function(navobj) {
- navobj.setparam("reset_page", "true");
- }
- });
- }
-
- $("#listing").html(response.listing);
-
- if (this.navobject.getparam("action") == "listmailbox") {
- this.setup_infinite_scroll(response);
- } else {
- this.disable_infinite_scroll();
- }
- },
-
- /**
- * Set the *unseen messages* counter for a particular mailbox in
- * the list. If the mailbox is currently selected, we force a
- * listing update.
- *
- */
- set_unseen_messages: function(mailbox, value) {
- if (this.poller.running_request) {
- return;
- }
- if (this.unseen_counters[mailbox] !== undefined &&
- value == this.unseen_counters[mailbox]) {
- return;
- }
-
- if (this.navobject.params.action == "listmailbox") {
- var curmb = this.get_current_mailbox();
- if (curmb == mailbox) {
- this.navobject.setparam("reset_page", "true").update(true);
- }
- }
-
- var $link = $('a[href="' + mailbox + '"]');
- var parts = mailbox.split(this.options.hdelimiter);
- var dname = " " + parts[parts.length - 1];
- var $span = $link.children("span:visible");
-
- this.unseen_counters[mailbox] = value;
- if (value) {
- $link.html(dname + " (" + value + ")");
- $link.addClass("unseen");
- } else {
- $link.html(dname);
- $link.removeClass("unseen");
- }
- $link.prepend($span);
- },
-
- /*
- * Increment or decrement the *unseen messages* counter of the
- * given mailbox.
- */
- change_unseen_messages: function(mailbox, offset) {
- if (this.unseen_counters[mailbox] === undefined) {
- this.unseen_counters[mailbox] = 0;
- }
- this.set_unseen_messages(mailbox, this.unseen_counters[mailbox] + offset);
- },
-
- /*
- * Returns a list containing the currently visible mailboxes (in
- * the left tree).
- */
- get_visible_mailboxes: function() {
- var res = [];
-
- $("#folders").find("ul:visible").children("li.droppable").each(function() {
- res.push(encodeURIComponent($(this).attr("name")));
- });
- return "mboxes=" + res.join(",");
- },
-
- /*
- * Poller callback.
- */
- poller_cb: function(data) {
- for (var mb in data) {
- this.set_unseen_messages(mb, parseInt(data[mb]));
- }
- },
-
- /**
- * Inject a new *clickbox* somewhere in the tree.
- *
- * @this Webmail
- * @param {Object} $container - box container
- */
- inject_clickbox: function($container) {
- $container.prepend($("
", {'class' : 'clickbox collapsed'}));
- },
-
- /*
- * Injects a single mailbox somewhere in the tree
- */
- inject_mailbox: function($parent, mailbox, linkname, unseen) {
- var $li = $(" ", {
- name: mailbox,
- 'class': "droppable"
- });
- var $link = $(" ", {
- name: linkname,
- href: mailbox
- });
- var parts = mailbox.split(this.options.hdelimiter);
- var linkcontent = " ";
- var displayname = linkcontent + parts[parts.length - 1];
-
- $li.append($link);
- $parent.append($li);
-
- if (unseen !== undefined) {
- $link.addClass("unseen");
- $link.html(displayname + " (" + unseen + ")");
- this.unseen_counters[$link.attr("href")] = unseen;
- } else {
- $link.html(displayname);
- }
- return $li;
- },
-
- /**
- * Inject new mailboxes under a given parent in the tree.
- *
- * @this Webmail
- * @param {Object} $parent - an existing node.
- * @param {Array} mboxes - list of mailboxes to inject
- */
- inject_mailboxes: function($parent, mboxes) {
- var $ul = $("", {
- name: $parent.attr("name"),
- 'class': "hidden nav"
- });
- var $plink = $parent.children("a");
-
- $parent.append($ul);
- if (!$parent.children("div").length) {
- this.inject_clickbox($parent);
- }
- for (var i = 0; i < mboxes.length; i++) {
- if ($parent.find('li[name="' + mboxes[i].name + '"]').length) {
- continue;
- }
- this.inject_mailbox(
- $ul, mboxes[i].name, $plink.attr("name"), mboxes[i].unseen
- );
- if (mboxes[i].sub !== undefined) {
- this.inject_clickbox($('li[name="' + mboxes[i].name + '"]'));
- }
- }
- this.init_droppables($ul.find(".droppable"));
- this.toggle_mbox_state($parent.children("div"), $ul);
- },
-
- /**
- * Download mailboxes from the server.
- *
- * @this Webmail
- * @param {Object} parent - parent node where mailboxes will be appended
- * @param {boolean} async - if true, the ajax call will be asynchronous
- */
- get_mailboxes: function(parent, async, with_unseen) {
- var args = "topmailbox=" + parent.attr("name");
-
- if (with_unseen) {
- args += "&unseen=true";
- }
- if (async === undefined) {
- async = true;
- }
- $.ajax({
- url: this.options.submboxes_url,
- dataType: 'json',
- async: async,
- data: args
- }).done($.proxy(function(data) {
- this.inject_mailboxes(parent, data);
- }, this));
- },
-
- /**
- * Open/Close a mailbox with children.
- *
- * This is an internal method.
- *
- * @this Webmail
- * @param {Object} $div - the
that was clicked
- * @param {Object} $ul - the element to show/hide
- */
- toggle_mbox_state: function($div, $ul) {
- if ($ul.hasClass("hidden")) {
- $div.removeClass("collapsed").addClass("expanded");
- $ul.removeClass("hidden").addClass("visible");
- } else {
- $div.removeClass("expanded").addClass("collapsed");
- $ul.removeClass("visible").addClass("hidden");
- }
- },
-
- /**
- * Click event : open or close a mailbox (user triggered).
- *
- * The first time it is opened, sub mailboxes will be downloaded
- * from the server and injected into the tree.
- *
- * @this Webmail
- * @param {Object} e - event object
- */
- mbox_state_callback: function(e) {
- e.preventDefault();
- e.stopPropagation();
- var $div = $(e.target);
- var $parent = $div.parents("li").first();
- var $ul = $parent.find('ul[name="' + $parent.attr("name") + '"]');
-
- if (!$ul.length) {
- var $link = $div.next();
- var with_unseen = ($link.attr("name") == "loadfolder") ? true : false;
- this.get_mailboxes($parent, true, with_unseen);
- return;
- }
- this.toggle_mbox_state($div, $ul);
- },
-
- /**
- * Unselect every selected mailbox.
- */
- reset_mb_selection: function() {
- $("a[name=loadfolder]").parent().removeClass("active").addClass("droppable");
- },
-
- /**
- * Select a particular mailbox (one already present in the DOM).
- *
- * @this Webmail
- * @param {Object|string} obj - mailbox to select
- */
- select_mailbox: function(obj) {
- var $obj = (typeof obj != "string") ? $(obj) : $('a[href="' + obj + '"]');
-
- this.reset_mb_selection();
- $obj.parents("ul").addClass("visible");
- $obj.parent().removeClass("droppable");
- $obj.parent().addClass("active");
- },
-
- /**
- * Try to select a particular sub-mailbox and load it from the
- * server if it's not present in the DOM. (nb: all parents needed
- * to access this mailbox are also loaded)
- *
- * @this Webmail
- * @param {string} mailbox - mailbox to select
- */
- load_and_select_mailbox: function(mailbox) {
- if (mailbox.indexOf(this.options.hdelimiter) == -1) {
- this.select_mailbox(mailbox);
- return;
- }
- this.reset_mb_selection();
-
- var parts = mailbox.split(this.options.hdelimiter);
- var curmb = parts[0], lastmb = "";
-
- for (var i = 1; i < parts.length; i++) {
- lastmb = curmb;
- curmb += this.options.hdelimiter + parts[i];
-
- var $link = $('a[href="' + curmb + '"]');
- var $container = $('li[name="' + lastmb + '"]');
-
- if ($link.length) {
- if ($container.children("div").hasClass("collapsed")) {
- this.toggle_mbox_state($container.children("div"), $container.children("ul"));
- }
- continue;
- }
-
- this.get_mailboxes($container, false);
- $container.children("div").addClass("expanded");
- $container.children("ul").addClass("visible");
- }
- $('li[name="' + mailbox + '"]').addClass("active");
- },
-
- /**
- * Click handler : select the parent mailbox of the mailbox being
- * created/modified.
- *
- * @param {Object} e - event object
- */
- select_parent_mailbox: function(e) {
- e.preventDefault();
- var $this = $(this);
- var $parent = $this.parent();
- var is_selected = $parent.hasClass("active");
-
- $("a[name=selectfolder]").parent().removeClass("active");
- if (!is_selected) {
- $parent.addClass("active");
- }
- },
-
- new_mailbox: function(e) {
- this.poller.pause();
- },
-
- /*
- * Edit the currently selected mailbox. Opens a modal box that
- * permits to change mailbox's name and more.
- */
- edit_mbox: function(e) {
- this.poller.pause();
-
- var $link = get_target(e, "a");
- if ($link.hasClass("disabled")) {
- e.preventDefault();
- return;
- }
- var $selected = $("#folders li.active").children("a");
-
- modalbox(e, undefined, $link.attr("href") + "?name=" + $selected.attr("href"),
- $.proxy(this.mboxform_cb, this), $.proxy(this.mboxform_close, this));
- },
-
- /*
- * Remove the currently selected mailbox.
- */
- remove_mbox: function(e) {
- var $link = get_target(e, "a");
- e.preventDefault();
- if ($link.hasClass("disabled")) return;
- if (!confirm(gettext("Remove the selected mailbox?"))) {
- return;
- }
-
- this.poller.pause();
- var $selected = $("#folders li.active").children("a");
-
- $.ajax({
- url: $link.attr("href") + "?name=" + $selected.attr("href"),
- dataType: 'json'
- }).done($.proxy(function(data) {
- this.remove_mbox_from_tree(this.navobject.getparam("mbox"));
- this.poller.resume();
- $("body").notify("success", gettext("Mailbox removed"), 2000);
- }, this));
- },
-
- /*
- * Remove a mailbox from the tree.
- *
- * It is a client-side action, no request is sent to the server.
- */
- remove_mbox_from_tree: function(mailbox) {
- var $container = (typeof mailbox === "string") ? $('li[name="' + mailbox + '"]') : mailbox;
- var $parent = $container.parent("ul");
-
- if ($parent.children("li").length == 1) {
- $parent.siblings("div").remove();
- $parent.remove();
- } else {
- $container.remove();
- }
- if (this.navobject.getparam("action") == "listmailbox") {
- this.select_mailbox($("a[href=INBOX]"));
- this.navobject.setparam("mbox", "INBOX").update();
- }
- },
-
- /*
- * Add a new mailbox into the tree. We check if the parent is
- * present before adding. If it's not present, we do nothing.
- */
- add_mailbox_to_tree: function(parent, mailbox) {
- var $parent;
-
- if (parent) {
- $parent = $("#folders").find('li[name="' + parent + '"]');
- if (!$parent.length) {
- return;
- }
- if (!$parent.children("div").length) {
- this.inject_clickbox($parent);
- }
- var $ul = $parent.children("ul");
- if (!$ul.length) {
- return;
- }
- $parent = $ul;
- mailbox = $parent.attr("name") + this.options.hdelimiter + mailbox;
- } else {
- $parent = $("#folders > div > ul");
- }
- var $li = this.inject_mailbox($parent, mailbox, "loadfolder");
- this.init_droppables($li);
- },
-
- /*
- * Rename a mailbox (client-side)
- * If needed, the mailbox will be moved to its new location.
- */
- rename_mailbox: function(oldname, newname, oldparent, newparent) {
- var oldpattern = (oldparent) ? oldparent + this.options.hdelimiter + oldname : oldname;
- var newpattern = (newparent) ? newparent + this.options.hdelimiter + newname : newname;
- var $link = $("#folders").find('a[href="' + oldpattern + '"]');
-
- if (oldname != newname) {
- var $span = $link.children("span");
-
- $link.html(" " + newname);
- $link.parent("li").attr("name", newpattern);
- $link.prepend($span);
- $link.attr("href", newpattern);
- this.navobject.setparam("mbox", newpattern).update(false, true);
- }
- if (oldparent != newparent) {
- this.remove_mbox_from_tree($link.parent("li"));
- this.add_mailbox_to_tree(newparent, newname);
- if (this.navobject.getparam("action") == "listmailbox") {
- this.navobject.setparam("mbox", newpattern).update();
- } else {
- this.select_mailbox("INBOX");
- }
- }
- },
-
- send_mark_request: function(e) {
-
- e.preventDefault();
- if (!this.htmltable.current_selection().length) {
- return;
- }
- var $link = $(e.target);
- var selection = [];
-
- this.htmltable.current_selection().each(function() {
- selection.push($(this).attr("id"));
- });
- $.ajax({
- url: $link.attr("href"),
- data: "ids=" + selection.join(","),
- dataType: 'json'
- }).done($.proxy(this.mark_callback, this));
- },
-
- send_mb_action: function(url, cb) {
- $.ajax({
- url: url,
- dataType: 'json'
- }).done($.proxy(function(data) {
- if (cb !== undefined) {
- cb.apply(this, [data]);
- }
- }, this));
- },
-
- /**
- * Click event: empty Trash folder.
- *
- * @this Webmail
- * @param {Object} e - event object
- */
- empty: function(e) {
- e.preventDefault();
- var $link = $(e.target);
-
- this.send_mb_action($link.attr("href"), function(data) {
- this.page_update(data);
- this.set_unseen_messages(data.mailbox, 0);
- });
- },
-
- /**
- * Compress the currently selected mailbox.
- *
- * @this {Webmail}
- * @param {object} e - event object
- */
- compress: function(e) {
- e.preventDefault();
- var $link = $(e.target);
- var $selected = $("#folders li.active").children("a");
-
- this.send_mb_action(
- "{0}?name={1}".format($link.attr("href"), $selected.attr("href"))
- );
- },
-
- delete_message: function(e) {
- var $link = get_target(e, "a");
- e.preventDefault();
- $.ajax({
- url: $link.attr("href"),
- dataType: 'json'
- }).done($.proxy(this.delete_callback, this));
- },
-
- delete_messages: function(e) {
- e.preventDefault();
- var $link = get_target(e, "a");
- if ($link.hasClass("disabled")) {
- return;
- }
- var msgs = this.htmltable.current_selection();
- var selection = [];
- var unseen_cnt = 0;
-
- if (!msgs.length) {
- return;
- }
- $link.addClass("disabled");
- $.each(msgs, function(idx, item) {
- var $tr = $(item);
- selection.push($tr.attr("id"));
- if ($tr.hasClass("unseen")) {
- unseen_cnt++;
- }
- });
- this.change_unseen_messages(this.get_current_mailbox(), -unseen_cnt);
- this.change_unseen_messages(this.options.trash, unseen_cnt);
- $.ajax({
- url: $link.attr("href"),
- data: {mbox: this.get_current_mailbox(), selection: selection}
- }).done($.proxy(this.delete_callback, this));
- },
-
- display_mode: function(e, value) {
- e.preventDefault();
- this.navobject.setparam("links", value).update();
- },
-
- /*
- * Action loaders
- */
-
- /*
- * Onclick callback used to load the content of a particular
- * mailbox. (activated when clicking on a mailbox's name)
- */
- _listmailbox_loader: function(event, obj, reset_page) {
- if (event) {
- event.preventDefault();
- }
- if (obj === undefined) {
- obj = $(event.target);
- }
- this.navobject.reset().setparams({
- action: "listmailbox",
- mbox: obj.attr("href")
- });
- if (reset_page) {
- this.navobject.setparam("reset_page", reset_page);
- }
- this.navobject.update();
- },
-
- /**
- * Click event: list the content of a particular mailbox.
- *
- * @this Webmail
- * @param {Object} event - event object
- */
- listmailbox_loader: function(event) {
- var $target = get_target(event, "a");
-
- if ($target.parent().hasClass("disabled")) {
- event.preventDefault();
- return;
- }
- this.select_mailbox(event.target);
- this._listmailbox_loader(event, $target, true);
- },
-
- /*
- * Special loader used for pagination links as we only need to
- * update the 'page' parameter.
- */
- getpage_loader: function(e) {
- var $link = $(e.target).parent();
- e.preventDefault();
- this.navobject.updateparams($link.attr("href")).update();
- },
-
- /*
- * Loader of the 'compose' action (called when the associated button
- * is clicked)
- */
- compose_loader: function(e) {
- var $link = get_target(e, 'a');
-
- e.preventDefault();
- this.navobject.reset().setparam("action", $link.attr("href")).update();
- },
-
- reply_loader: function(e) {
- var $link = get_target(e, "a");
- e.preventDefault();
- this.navobject.reset().updateparams($link.attr("href")).update();
- },
-
- sendmail: function(e) {
- var $link = $(e.target);
- var $form = $("#composemail");
-
- e.preventDefault();
- $link.attr("disabled", "disabled");
- if (this.editormode == "html") {
- CKEDITOR.instances[this.editorid].updateElement();
- }
- var args = $form.serialize();
-
- $.ajax({
- url: $form.attr("action"),
- data: args,
- dataType: 'json',
- type: 'POST',
- global: false
- }).done($.proxy(function(data) {
- this._listmailbox_loader(null, $("#folders").find("li[class*=active]").children("a"));
- $("body").notify("success", gettext("Message sent"), 2000);
- }, this)).fail($.proxy(function(jqxhr) {
- var data = $.parseJSON(jqxhr.responseText);
- if (data !== undefined) {
- this.compose_callback(data);
- }
- $("a[name=sendmail]").attr("disabled", null);
- }, this));
- },
-
- /*
- * Loader of the 'viewmail' action
- */
- viewmail_loader: function(e) {
- var $div = $(e.target).parents(".email");
- var curmb = this.get_current_mailbox();
-
- e.preventDefault();
- if ($div.hasClass("disabled")) {
- return;
- }
- $div.addClass("disabled");
- if ($div.hasClass("unseen")) {
- var mb = this.get_current_mailbox();
- this.change_unseen_messages(mb, -1);
- }
- this.navobject.reset().setparams({
- action: "viewmail",
- mbox: curmb,
- mailid: $div.attr("id")
- }).update();
- },
-
- /*
- * Ajax navigation callbacks
- */
-
- /**
- * Navigation callback: listmailbox.
- *
- * @this Webmail
- * @param {Object} resp - ajax response (JSON)
- */
- listmailbox_callback: function(resp) {
- this.store_nav_params();
- this.page_update(resp);
- $("#emails").htmltable({
- row_selector: "div.email"
- });
- this.htmltable = $("#emails").data("htmltable");
- this.init_draggables();
- $("#listing").css("overflow-y", "auto");
- if (this.navobject.hasparam("reset_page")) {
- this.navobject.delparam("reset_page").update(false, true);
- }
- },
-
- add_field: function(e, name) {
- e.preventDefault();
- $("label[for=id_" + name + "]").parent().show();
- $(e.target).hide();
- this.resize_compose_body();
- if (this.editormode == "html") {
- this.resize_editor();
- }
- },
-
- /**
- * Compose form loading and initialization.
- */
- compose_callback: function(resp) {
- this.page_update(resp);
- $("#add_cc").click($.proxy(function(e) { this.add_field(e, "cc"); }, this));
- $("#add_cci").click($.proxy(function(e) { this.add_field(e, "cci"); }, this));
- this.editormode = resp.editor;
- if (resp.editor == "html") {
- var instance = CKEDITOR.instances[this.editorid];
-
- $(window).resize($.proxy(this.resize_editor, this));
- if (instance) {
- CKEDITOR.remove(instance);
- }
- CKEDITOR.replace(this.editorid, {
- customConfig: get_static_url("js/editor_config.js")
- });
- CKEDITOR.on("instanceReady", $.proxy(function(evt) {
- this.resize_editor();
- }, this));
- }
- if (resp.id !== undefined) {
- this.navobject.setparam("id", resp.id).update(false, true);
- }
-
- this.resize_compose_body();
- },
-
- /**
- * Callback of the 'viewmail' action
- *
- * @this Webmail
- * @param {Object} resp - AJAX call response (JSON)
- */
- viewmail_callback: function(resp) {
- this.page_update(resp);
- $("#listing").css("overflow-y", "hidden");
- $("a[name=back]").click($.proxy(function(e) {
- e.preventDefault();
- this.go_back_to_listing();
- }, this));
- },
-
- mark_callback: function(data) {
- if (data.action == "read") {
- this.htmltable.current_selection().removeClass("unseen");
- } else {
- this.htmltable.current_selection().addClass("unseen");
- }
- if (data.unseen !== undefined && data.mbox) {
- this.set_unseen_messages(data.mbox, data.unseen);
- }
- },
-
- delete_callback: function(data) {
- this.go_back_to_listing();
- if (this.get_current_mailbox() != this.options.trash) {
- $("a[name=totrash]").removeClass("disabled");
- }
- $("body").notify("success", data, 2000);
- },
-
- /*
- * Mailbox form initialization
- */
- mboxform_cb: function() {
- $("#mboxform").find("input").keypress(function(e) {
- if (e.which == 13) e.preventDefault();
- });
- $(".submit").on('click', $.proxy(function(e) {
- var $link = $("#folders2 li.active").children("a");
-
- simple_ajax_form_post(e, {
- reload_on_success: false,
- formid: "mboxform",
- extradata: ($link.length) ? "parent_folder=" + $link.attr("href") : "",
- success_cb: $.proxy(this.mboxform_success, this)
- });
- }, this));
- },
-
- mboxform_success: function(data) {
- $("body").notify('success', data.respmsg, 2000);
- if (data.oldmb === undefined) {
- this.add_mailbox_to_tree(data.parent, data.newmb);
- } else if (data.newmb) {
- this.rename_mailbox(data.oldmb, data.newmb, data.oldparent, data.newparent);
- }
- this.poller.resume();
- },
-
- /*
- * Just a simple 'onclose' callback to check if the poller has
- * been resumed (useful when the user has cancelled the action)
- */
- mboxform_close: function() {
- if (this.poller.paused) {
- this.poller.resume();
- }
- },
-
- /*
- * Attachments form
- */
- attachments_init: function() {
- $("#submit").click(function(e) {
- e.preventDefault();
- if ($("#id_attachment").val() === "") {
- return;
- }
- $("#upload_status").css("display", "block");
- $("#submit").attr("disabled", "disabled");
- $("#uploadfile").submit();
- });
- $("a[name=delattachment]").click(this.del_attachment);
- $(".modal").one("hide.bs.modal", $.proxy(this.close_attachments, this));
- },
-
- _reset_upload_form: function() {
- $("#upload_status").css("display", "none");
- $("#submit").attr("disabled", null);
- },
-
- upload_success: function(fname, tmpname) {
- this._reset_upload_form();
- var $delbtn = $(" ", {
- name: "delattachment",
- href: this.options.delattachment_url + "?name=" + tmpname,
- html: " "
- });
- var $label = $(" ", {html: fname});
- var $div = $("
", {'class': "row"}).append(
- $("
", {"class": "col-sm-12"}).append($delbtn, $label)
- );
-
- $delbtn.click(this.del_attachment);
- $("#id_attachment").val("");
- $("#attachment_list").append($div);
- },
-
- upload_error: function(msg) {
- this._reset_upload_form();
- $(".modal-header").notify('error', msg);
- },
-
- del_attachment: function(e) {
- e.preventDefault();
- var $this = $(this);
-
- $.ajax({
- url: $this.attr("href")
- }).done(function() {
- $this.parent().remove();
- });
- },
-
- /**
- * Update the counter of currently attached files.
- */
- update_files_counter: function() {
- var nfiles = $("a[name=delattachment]").length;
-
- $("#attachment_counter").html("(" + nfiles + ")");
- },
-
- /**
- * Attachments form "on close" callback.
- */
- close_attachments: function() {
- this.update_files_counter();
- },
-
- /*
- * Drag & Drop feature to move message(s) between mailboxes
- */
- init_draggables: function() {
- var plug = this;
-
- $("img[name=drag]").draggable({
- opacity: 0.9,
- helper: function(e) {
- var $this = $(this);
- var $row = $this.parents("div.email");
-
- if (!plug.htmltable.is_selected($row)) {
- var $input = $row.find('input[type=checkbox]');
- plug.htmltable.select_row($row);
- $input.prop('checked', true);
- }
-
- var nmsgs = plug.htmltable.current_selection().length;
-
- var $dragbox = $("
", {
- id: "draggeditems",
- 'class': "well dragbox"
- })
- .appendTo($(document.body))
- .offset({
- top: $this.offset().top,
- left: $this.offset().left
- });
- $dragbox.html(interpolate(ngettext("Moving %s message",
- "Moving %s messages", nmsgs), [nmsgs]));
- return $dragbox;
- }
- });
- },
-
- init_droppables: function(set) {
- var plug = this;
- var $set = (set === undefined) ? $(".droppable") : set;
-
- $set.droppable({
- greedy: true,
- hoverClass: "active",
-
- drop: function(e, ui) {
- var $this = $(this);
- var selection = [];
- var unseen_cnt = 0;
- var from = plug.get_current_mailbox();
- var to = gethref($this.find("a"));
-
- plug.htmltable.current_selection().each(function() {
- var $this = $(this);
- selection.push($this.attr("id"));
- if ($this.hasClass("unseen")) {
- unseen_cnt++;
- }
- });
- $.ajax({
- url: plug.options.move_url,
- data: "msgset=" + selection.join() + "&to=" + to,
- dataType: 'json'
- }).done(function(data) {
- if (unseen_cnt) {
- plug.change_unseen_messages(from, -unseen_cnt);
- plug.change_unseen_messages(to, unseen_cnt);
- }
- plug.listmailbox_callback(data);
- });
- }
- });
- }
-};
diff --git a/modoboa/extensions/webmail/templates/webmail/attachments.html b/modoboa/extensions/webmail/templates/webmail/attachments.html
deleted file mode 100644
index 1b0c5d59a..000000000
--- a/modoboa/extensions/webmail/templates/webmail/attachments.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% extends "common/generic_modal_form.html" %}{% load url from future %}
-{% load i18n %}
-{% load static %}
-{% block modalbody %}
-{{ block.super }}
-
-
-
-
-
-
-
{% trans "Uploading.." %}
-
-
-
- {% for att in attachments %}
-
-
-
-
-
-
{{ att.fname }}
-
-
- {% endfor %}
-
-{% endblock %}
diff --git a/modoboa/extensions/webmail/templates/webmail/compose.html b/modoboa/extensions/webmail/templates/webmail/compose.html
deleted file mode 100644
index 4fb607529..000000000
--- a/modoboa/extensions/webmail/templates/webmail/compose.html
+++ /dev/null
@@ -1,43 +0,0 @@
-{% load i18n form_tags %}{% load url from future %}
-
-
-
diff --git a/modoboa/extensions/webmail/templates/webmail/compose_menubar.html b/modoboa/extensions/webmail/templates/webmail/compose_menubar.html
deleted file mode 100644
index f254e0ab0..000000000
--- a/modoboa/extensions/webmail/templates/webmail/compose_menubar.html
+++ /dev/null
@@ -1,13 +0,0 @@
-{% extends "common/buttons_list.html" %}
-
-{% load i18n %}
-
-{% block extra_buttons %}
-
-{% endblock %}
diff --git a/modoboa/extensions/webmail/templates/webmail/email_list.html b/modoboa/extensions/webmail/templates/webmail/email_list.html
deleted file mode 100644
index bb20800a1..000000000
--- a/modoboa/extensions/webmail/templates/webmail/email_list.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% load i18n %}
-{% load webmail_tags %}
-{% load static %}
-
-{% if with_top_div %}{% endif %}
- {% for email in email_list %}
-
-
-
-
-
-
-
- {{ email.subject|parse_imap_header:"subject" }}
-
- {{ email.from|parse_imap_header:"from" }}
-
-
-
- {{ email.date|parse_imap_header:"date" }}
-
{% if email.answered %} {% endif %}{% if email.forwarded %} {% endif %}{% if email.attachments %} {% endif %}
-
-
- {% endfor %}
-{% if with_top_div %}
{% endif %}
diff --git a/modoboa/extensions/webmail/templates/webmail/folder.html b/modoboa/extensions/webmail/templates/webmail/folder.html
deleted file mode 100644
index c71daa85d..000000000
--- a/modoboa/extensions/webmail/templates/webmail/folder.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% extends "common/generic_modal_form.html" %}
-{% load i18n webmail_tags %}
-{% block extrafields %}
-
-
-
- {% print_mailboxes mboxes selected withunseen selectonly hdelimiter %}
-
-
-{% endblock %}
diff --git a/modoboa/extensions/webmail/templates/webmail/folders.html b/modoboa/extensions/webmail/templates/webmail/folders.html
deleted file mode 100644
index 3072b1677..000000000
--- a/modoboa/extensions/webmail/templates/webmail/folders.html
+++ /dev/null
@@ -1,4 +0,0 @@
-{% load i18n webmail_tags %}
-
diff --git a/modoboa/extensions/webmail/templates/webmail/headers.html b/modoboa/extensions/webmail/templates/webmail/headers.html
deleted file mode 100644
index 2c20c9de6..000000000
--- a/modoboa/extensions/webmail/templates/webmail/headers.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% extends "common/mailheaders.html" %}{% load i18n %}{% load url from future %}
-{% block extraheaders %}{% if attachments %}
-
-
-
{% url "webmail:attachment_get" as url %}
- {% for key, fname in attachments.items %}
-
{{ fname }}
- {% endfor %}
-
-
-{% endif %}{% endblock %}
diff --git a/modoboa/extensions/webmail/templates/webmail/index.html b/modoboa/extensions/webmail/templates/webmail/index.html
deleted file mode 100644
index 96d68e9de..000000000
--- a/modoboa/extensions/webmail/templates/webmail/index.html
+++ /dev/null
@@ -1,75 +0,0 @@
-{% extends "twocols.html" %}{% load i18n lib_tags webmail_tags %}{% load url from future %}
-{% load static %}
-{% block pagetitle %}Webmail{% endblock %}
-{% block extra_css %}
-
-
-{% endblock %}
-
-{% block extra_js %}
-
-
-
-
-
-
-
-
-{% endblock %}
-
-{% block leftcol %}
-
-
-
- {{ mboxes }}
-
-
-
-{% endblock %}
-
-{% block apparea %}
-
-
-
-{% endblock %}
-
diff --git a/modoboa/extensions/webmail/templates/webmail/main_action_bar.html b/modoboa/extensions/webmail/templates/webmail/main_action_bar.html
deleted file mode 100644
index 9a520d7ea..000000000
--- a/modoboa/extensions/webmail/templates/webmail/main_action_bar.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% extends "common/buttons_list.html" %}{% load i18n %}
-
-{% block before_menubar %}
-
- {% include "common/email_searchbar.html" with extraopts=extraopts %}
-
-{% endblock %}
-
-{% block menubar_classes %}col-xs-7{% endblock %}
diff --git a/modoboa/extensions/webmail/templates/webmail/upload_done.html b/modoboa/extensions/webmail/templates/webmail/upload_done.html
deleted file mode 100644
index 1ece2ce82..000000000
--- a/modoboa/extensions/webmail/templates/webmail/upload_done.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/modoboa/extensions/webmail/templatetags/__init__.py b/modoboa/extensions/webmail/templatetags/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/webmail/templatetags/webmail_tags.py b/modoboa/extensions/webmail/templatetags/webmail_tags.py
deleted file mode 100644
index 83b2f3d95..000000000
--- a/modoboa/extensions/webmail/templatetags/webmail_tags.py
+++ /dev/null
@@ -1,221 +0,0 @@
-# coding: utf-8
-from django import template
-from django.template.loader import render_to_string
-from django.utils.translation import ugettext as _
-from django.core.urlresolvers import reverse
-from django.conf import settings
-
-from modoboa.extensions.webmail.lib import (
- imapheader, separate_mailbox
-)
-from modoboa.lib import parameters
-
-register = template.Library()
-
-
-@register.simple_tag
-def viewmail_menu(selection, folder, user, mail_id=None):
- """Menu of the viewmail location."""
- entries = [
- {"name": "back",
- "url": "javascript:history.go(-1)",
- "img": "fa fa-arrow-left",
- "class": "btn-default",
- "label": _("Back")},
- {"name": "reply",
- "url": "action=reply&mbox=%s&mailid=%s" % (folder, mail_id),
- "img": "fa fa-mail-reply",
- "class": "btn-primary",
- "label": _("Reply"),
- "menu": [
- {"name": "replyall",
- "url": "action=reply&mbox=%s&mailid=%s&all=1" % (folder, mail_id),
- "img": "fa fa-mail-reply-all",
- "label": _("Reply all")},
- {"name": "forward",
- "url": "action=forward&mbox=%s&mailid=%s" % (folder, mail_id),
- "img": "fa fa-mail-forward",
- "label": _("Forward")},
- ]},
- {"name": "delete",
- "img": "fa fa-trash",
- "class": "btn-danger",
- "url": "{0}?mbox={1}&selection[]={2}".format(
- reverse("webmail:mail_delete"), folder, mail_id),
- "title": _("Delete")
- },
- {"name": "display_options",
- "title": _("Display options"),
- "img": "fa fa-cog",
- "menu": [
- {"name": "activate_links",
- "label": _("Activate links")},
- {"name": "disable_links",
- "label": _("Disable links")}
- ]
- }
- ]
- menu = render_to_string('common/buttons_list.html',
- {"selection": selection, "entries": entries,
- "user": user, "extraclasses": "pull-left"})
-
- return menu
-
-
-@register.simple_tag
-def compose_menu(selection, backurl, user, **kwargs):
- """The menu of the compose action."""
- entries = [
- {"name": "back",
- "url": "javascript:history.go(-2);",
- "img": "fa fa-arrow-left",
- "class": "btn-default",
- "label": _("Back")},
- {"name": "sendmail",
- "url": "",
- "img": "fa fa-send",
- "class": "btn-default btn-primary",
- "label": _("Send")},
- ]
- context = {
- "selection": selection, "entries": entries, "user": user
- }
- context.update(kwargs)
- return render_to_string('webmail/compose_menubar.html', context)
-
-
-@register.simple_tag
-def listmailbox_menu(selection, folder, user):
- """The menu of the listmailbox action."""
- entries = [
- {"name": "totrash",
- "title": _("Delete"),
- "class": "btn-danger",
- "img": "fa fa-trash",
- "url": reverse("webmail:mail_delete")
- },
- {"name": "actions",
- "label": _("Actions"),
- "class": "btn btn-default",
- "menu": [
- {"name": "mark-read",
- "label": _("Mark as read"),
- "url": "{0}?status=read".format(
- reverse("webmail:mail_mark", args=[folder]))},
- {"name": "mark-unread",
- "label": _("Mark as unread"),
- "url": "{0}?status=unread".format(
- reverse("webmail:mail_mark", args=[folder]))},
- ]
- },
- ]
- if folder == parameters.get_user(user, "TRASH_FOLDER"):
- entries[0]["class"] += " disabled"
- entries[1]["menu"] += [
- {"name": "empty",
- "label": _("Empty folder"),
- "url": "{0}?name={1}".format(
- reverse("webmail:trash_empty"), folder)}
- ]
- return render_to_string('webmail/main_action_bar.html', {
- 'selection': selection, 'entries': entries, 'user': user, 'css': "nav",
- 'STATIC_URL': settings.STATIC_URL
- })
-
-
-@register.simple_tag
-def print_mailboxes(
- tree, selected=None, withunseen=False, selectonly=False,
- hdelimiter='.'):
- """Display a tree of mailboxes and sub-mailboxes.
-
- :param tree: the mailboxes to display
- """
- result = ""
-
- for mbox in tree:
- cssclass = ""
- name = mbox["path"] if "sub" in mbox else mbox["name"]
- label = separate_mailbox(mbox["name"], hdelimiter)[0]
- if mbox.get("removed", False):
- cssclass = "disabled"
- elif selected == name:
- cssclass = "active"
- result += " \n" % (name, cssclass)
- cssclass = ""
- extra_attrs = ""
- if withunseen and "unseen" in mbox:
- label += " (%d)" % mbox["unseen"]
- cssclass += " unseen"
- extra_attrs = ' data-toggle="%d"' % mbox["unseen"]
-
- if "sub" in mbox:
- if selected is not None and selected != name and selected.count(
- name):
- ul_state = "visible"
- div_state = "expanded"
- else:
- ul_state = "hidden"
- div_state = "collapsed"
- result += "
" % div_state
-
- result += "" % (
- "path" in mbox and mbox["path"] or mbox["name"], cssclass,
- 'selectfolder' if selectonly else 'loadfolder', extra_attrs
- )
-
- iclass = mbox["class"] if "class" in mbox \
- else "fa fa-folder"
- result += " %s " % (iclass, label)
-
- if "sub" in mbox and mbox["sub"]:
- result += "" % (
- mbox["path"], ul_state) + print_mailboxes(
- mbox["sub"], selected, withunseen, selectonly, hdelimiter
- ) + " \n"
- result += " \n"
- return result
-
-
-@register.simple_tag
-def mboxes_menu():
- """Mailboxes menu."""
- entries = [
- {"name": "newmbox",
- "url": reverse("webmail:folder_add"),
- "img": "fa fa-plus",
- "label": _("Create a new mailbox"),
- "modal": True,
- "modalcb": "webmail.mboxform_cb",
- "closecb": "webmail.mboxform_close",
- "class": "btn-default btn-xs"},
- {"name": "editmbox",
- "url": reverse("webmail:folder_change"),
- "img": "fa fa-edit",
- "label": _("Edit the selected mailbox"),
- "class": "btn-default btn-xs"},
- {"name": "removembox",
- "url": reverse("webmail:folder_delete"),
- "img": "fa fa-trash",
- "label": _("Remove the selected mailbox"),
- "class": "btn-default btn-xs"},
- {"name": "compress",
- "img": "fa fa-compress",
- "label": _("Compress folder"),
- "class": "btn-default btn-xs",
- "url": reverse("webmail:folder_compress")}
- ]
-
- return render_to_string('common/menu.html', dict(
- entries=entries, css="dropdown-menu"
- ))
-
-
-@register.filter
-def parse_imap_header(value, header):
- """Simple template tag to display a IMAP header."""
- try:
- value = getattr(imapheader, "parse_%s" % header)(value)
- except AttributeError:
- pass
- return value
diff --git a/modoboa/extensions/webmail/urls.py b/modoboa/extensions/webmail/urls.py
deleted file mode 100644
index e32192204..000000000
--- a/modoboa/extensions/webmail/urls.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# coding: utf-8
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns(
- 'modoboa.extensions.webmail.views',
-
- url(r'^$', "index", name="index"),
- url(r'^submailboxes', "submailboxes", name="submailboxes_get"),
- url(r'^getmailcontent', 'getmailcontent', name="mailcontent_get"),
- url(r'^unseenmsgs', 'check_unseen_messages', name="unseen_messages_check"),
-
- url(r'^delete/$', 'delete', name="mail_delete"),
- url(r'^move/$', "move", name="mail_move"),
- url(r'^mark/(?P.+)/$', "mark", name="mail_mark"),
-
- url(r'^newfolder/$', "newfolder", name="folder_add"),
- url(r'^editfolder/$', "editfolder", name="folder_change"),
- url(r'^delfolder/$', "delfolder", name="folder_delete"),
- url(r'^compressfolder/$', "folder_compress", name="folder_compress"),
- url(r'^emptytrash/$', "empty", name="trash_empty"),
-
- url(r'^attachments/$', 'attachments', name="attachment_list"),
- url(r'^delattachment/$', 'delattachment', name="attachment_delete"),
- url(r'^getattachment/$', 'getattachment', name="attachment_get"),
-)
diff --git a/modoboa/extensions/webmail/views.py b/modoboa/extensions/webmail/views.py
deleted file mode 100644
index 230ddc230..000000000
--- a/modoboa/extensions/webmail/views.py
+++ /dev/null
@@ -1,618 +0,0 @@
-# coding: utf-8
-"""
-Webmail extension views.
-"""
-
-import os
-
-from rfc6266 import build_header
-
-from django.conf import settings
-from django.http import HttpResponse
-from django.shortcuts import render
-from django.template import Template, Context
-from django.utils.translation import ugettext as _, ungettext
-from django.core.urlresolvers import reverse
-from django.contrib.auth.decorators import login_required
-from django.views.decorators.csrf import csrf_exempt
-from django.views.decorators.gzip import gzip_page
-
-from modoboa.lib import parameters
-from modoboa.lib.exceptions import ModoboaException, BadRequest
-from modoboa.lib.paginator import Paginator
-from modoboa.lib.web_utils import (
- _render_to_string, ajax_response, render_to_json_response
-)
-from modoboa.extensions.admin.lib import needs_mailbox
-from .exceptions import UnknownAction
-from .forms import (
- FolderForm, AttachmentForm, ComposeMailForm, ForwardMailForm
-)
-from .lib import (
- decode_payload, AttachmentUploadHandler,
- save_attachment, EmailSignature,
- clean_attachments, set_compose_session, send_mail,
- ImapEmail, WebmailNavigationParameters, ReplyModifier, ForwardModifier,
- get_imapconnector, IMAPconnector, separate_mailbox
-)
-from .templatetags import webmail_tags
-
-
-@login_required
-@needs_mailbox()
-@gzip_page
-def getattachment(request):
- """Fetch a message attachment
-
- FIXME: par manque de caching, le bodystructure du message est
- redemandé pour accéder aux headers de cette pièce jointe.
-
- :param request: a ``Request`` object
- """
- mbox = request.GET.get("mbox", None)
- mailid = request.GET.get("mailid", None)
- pnum = request.GET.get("partnumber", None)
- fname = request.GET.get("fname", None)
- if not mbox or not mailid or not pnum or not fname:
- raise BadRequest(_("Invalid request"))
-
- imapc = get_imapconnector(request)
- partdef, payload = imapc.fetchpart(mailid, mbox, pnum)
- resp = HttpResponse(decode_payload(partdef["encoding"], payload))
- resp["Content-Type"] = partdef["Content-Type"]
- resp["Content-Transfer-Encoding"] = partdef["encoding"]
- resp["Content-Disposition"] = build_header(fname)
- if int(partdef["size"]) < 200:
- resp["Content-Length"] = partdef["size"]
- return resp
-
-
-@login_required
-@needs_mailbox()
-def move(request):
- for arg in ["msgset", "to"]:
- if arg not in request.GET:
- raise BadRequest(_("Invalid request"))
- mbc = get_imapconnector(request)
- navparams = WebmailNavigationParameters(request)
- mbc.move(request.GET["msgset"], navparams.get('mbox'), request.GET["to"])
- resp = listmailbox(request, navparams.get('mbox'), update_session=False)
- return render_to_json_response(resp)
-
-
-@login_required
-@needs_mailbox()
-def delete(request):
- mbox = request.GET.get("mbox", None)
- selection = request.GET.getlist("selection[]", None)
- if mbox is None or selection is None:
- raise BadRequest(_("Invalid request"))
- selection = [item for item in selection if item.isdigit()]
- mbc = get_imapconnector(request)
- mbc.move(",".join(selection), mbox,
- parameters.get_user(request.user, "TRASH_FOLDER"))
- count = len(selection)
- message = ungettext("%(count)d message deleted",
- "%(count)d messages deleted",
- count) % {"count": count}
- return render_to_json_response(message)
-
-
-@login_required
-@needs_mailbox()
-def mark(request, name):
- status = request.GET.get("status", None)
- ids = request.GET.get("ids", None)
- if status is None or ids is None:
- raise BadRequest(_("Invalid request"))
- imapc = get_imapconnector(request)
- try:
- getattr(imapc, "mark_messages_%s" % status)(name, ids)
- except AttributeError:
- raise UnknownAction
-
- return render_to_json_response({
- 'action': status, 'mbox': name,
- 'unseen': imapc.unseen_messages(name)
- })
-
-
-@login_required
-@needs_mailbox()
-def empty(request):
- """Empty the trash folder."""
- name = request.GET.get("name", None)
- if name != parameters.get_user(request.user, "TRASH_FOLDER"):
- raise BadRequest(_("Invalid request"))
- get_imapconnector(request).empty(name)
- content = "%s
" % _("Empty mailbox")
- return render_to_json_response({
- 'listing': content, 'mailbox': name, 'pages': [1]
- })
-
-
-@login_required
-@needs_mailbox()
-def folder_compress(request):
- """Compress a mailbox."""
- name = request.GET.get("name", None)
- if name is None:
- raise BadRequest(_("Invalid request"))
- imapc = get_imapconnector(request)
- imapc.compact(name)
- return render_to_json_response({})
-
-
-@login_required
-@needs_mailbox()
-def newfolder(request, tplname="webmail/folder.html"):
- mbc = IMAPconnector(user=request.user.username,
- password=request.session["password"])
-
- if request.method == "POST":
- form = FolderForm(request.POST)
- if form.is_valid():
- pf = request.POST.get("parent_folder", None)
- mbc.create_folder(form.cleaned_data["name"], pf)
- return render_to_json_response({
- 'respmsg': _("Mailbox created"),
- 'newmb': form.cleaned_data["name"], 'parent': pf
- })
-
- return render_to_json_response({'form_errors': form.errors}, status=400)
-
- ctx = {"title": _("Create a new mailbox"),
- "formid": "mboxform",
- "action": reverse("webmail:folder_add"),
- "action_label": _("Create"),
- "action_classes": "submit",
- "withunseen": False,
- "selectonly": True,
- "mboxes": mbc.getmboxes(request.user),
- "hdelimiter": mbc.hdelimiter,
- "form": FolderForm(),
- "selected": None}
- return render(request, tplname, ctx)
-
-
-@login_required
-@needs_mailbox()
-def editfolder(request, tplname="webmail/folder.html"):
- mbc = IMAPconnector(user=request.user.username,
- password=request.session["password"])
- ctx = {"title": _("Edit mailbox"),
- "formid": "mboxform",
- "action": reverse("webmail:folder_change"),
- "action_label": _("Update"),
- "action_classes": "submit",
- "withunseen": False,
- "selectonly": True,
- "hdelimiter": mbc.hdelimiter}
-
- if request.method == "POST":
- form = FolderForm(request.POST)
- if form.is_valid():
- pf = request.POST.get("parent_folder", None)
- oldname, oldparent = separate_mailbox(
- request.POST["oldname"], sep=mbc.hdelimiter
- )
- res = {'respmsg': _("Mailbox updated")}
- if form.cleaned_data["name"] != oldname \
- or (pf != oldparent):
- newname = form.cleaned_data["name"] if pf is None \
- else mbc.hdelimiter.join([pf, form.cleaned_data["name"]])
- mbc.rename_folder(request.POST["oldname"], newname)
- res["oldmb"] = oldname
- res["newmb"] = form.cleaned_data["name"]
- res["oldparent"] = oldparent
- res["newparent"] = pf
- WebmailNavigationParameters(request).remove('mbox')
- return render_to_json_response(res)
-
- return render_to_json_response({'form_errors': form.errors}, status=400)
-
- name = request.GET.get("name", None)
- if name is None:
- raise BadRequest(_("Invalid request"))
- shortname, parent = separate_mailbox(name, sep=mbc.hdelimiter)
- ctx = {"title": _("Edit mailbox"),
- "formid": "mboxform",
- "action": reverse("webmail:folder_change"),
- "action_label": _("Update"),
- "action_classes": "submit",
- "withunseen": False,
- "selectonly": True,
- "hdelimiter": mbc.hdelimiter,
- "mboxes": mbc.getmboxes(request.user, until_mailbox=parent),
- "form": FolderForm(),
- "selected": parent}
- ctx["form"].fields["oldname"].initial = name
- ctx["form"].fields["name"].initial = shortname
- return render(request, tplname, ctx)
-
-
-@login_required
-@needs_mailbox()
-def delfolder(request):
- name = request.GET.get("name", None)
- if name is None:
- raise BadRequest(_("Invalid request"))
- mbc = IMAPconnector(user=request.user.username,
- password=request.session["password"])
- mbc.delete_folder(name)
- WebmailNavigationParameters(request).remove('mbox')
- return ajax_response(request)
-
-
-@login_required
-@csrf_exempt
-@needs_mailbox()
-def attachments(request, tplname="webmail/attachments.html"):
- if request.method == "POST":
- csuploader = AttachmentUploadHandler()
- request.upload_handlers.insert(0, csuploader)
- error = None
- form = AttachmentForm(request.POST, request.FILES)
- if form.is_valid():
- try:
- fobj = request.FILES["attachment"]
- tmpname = save_attachment(fobj)
- request.session["compose_mail"]["attachments"] \
- += [{"fname": str(fobj),
- "content-type": fobj.content_type,
- "size": fobj.size,
- "tmpname": os.path.basename(tmpname)}]
- request.session.modified = True
- return render(request, "webmail/upload_done.html", {
- "status": "ok", "fname": request.FILES["attachment"],
- "tmpname": os.path.basename(tmpname)
- })
- except ModoboaException as inst:
- error = _("Failed to save attachment: ") + str(inst)
-
- if csuploader.toobig:
- error = _("Attachment is too big (limit: %s)"
- % parameters.get_admin("MAX_ATTACHMENT_SIZE"))
- return render(request, "webmail/upload_done.html", {
- "status": "ko", "error": error
- })
- ctx = {
- "title": _("Attachments"),
- "formid": "uploadfile",
- "target": "upload_target",
- "enctype": "multipart/form-data",
- "form": AttachmentForm(),
- "action": reverse("webmail:attachment_list"),
- "attachments": request.session["compose_mail"]["attachments"]
- }
- return render(request, tplname, ctx)
-
-
-@login_required
-@needs_mailbox()
-def delattachment(request):
- if "compose_mail" not in request.session \
- or "name" not in request.GET \
- or not request.GET["name"]:
- return ajax_response(request, "ko", respmsg=_("Bad query"))
-
- error = None
- for att in request.session["compose_mail"]["attachments"]:
- if att["tmpname"] == request.GET["name"]:
- request.session["compose_mail"]["attachments"].remove(att)
- fullpath = os.path.join(
- settings.MEDIA_ROOT, "webmail", att["tmpname"]
- )
- try:
- os.remove(fullpath)
- except OSError as e:
- error = _("Failed to remove attachment: ") + str(e)
- break
- request.session.modified = True
- return ajax_response(request)
- if error is None:
- error = _("Unknown attachment")
- return ajax_response(request, "ko", respmsg=error)
-
-
-def render_mboxes_list(request, imapc):
- """Return the HTML representation of a mailboxes list
-
- :param request: a ``Request`` object
- :param imapc: an ``IMAPconnector` object
- :return: a string
- """
- curmbox = WebmailNavigationParameters(request).get("mbox", "INBOX")
- return _render_to_string(request, "webmail/folders.html", {
- "selected": curmbox,
- "mboxes": imapc.getmboxes(request.user),
- "withunseen": True
- })
-
-
-def listmailbox(request, defmailbox="INBOX", update_session=True):
- """Mailbox content listing.
-
- Return a list of messages contained in the specified mailbox. The
- number of elements returned depends on the ``MESSAGES_PER_PAGE``
- parameter. (user preferences)
-
- :param request: a ``Request`` object
- :param defmailbox: the default mailbox (when not present inside
- request arguments)
- :return: a dictionnary
- """
- navparams = WebmailNavigationParameters(request, defmailbox)
- previous_page_id = int(navparams["page"]) if "page" in navparams else None
- if update_session:
- navparams.store()
- mbox = navparams.get('mbox')
- page_id = int(navparams["page"])
- mbc = get_imapconnector(request)
- mbc.parse_search_parameters(
- navparams.get("criteria"), navparams.get("pattern"))
-
- paginator = Paginator(
- mbc.messages_count(folder=mbox, order=navparams.get("order")),
- int(parameters.get_user(request.user, "MESSAGES_PER_PAGE"))
- )
- page = paginator.getpage(page_id)
- content = ""
- if page is not None:
- email_list = mbc.fetch(page.id_start, page.id_stop, mbox)
- content = _render_to_string(request, "webmail/email_list.html", {
- "email_list": email_list,
- "page": page_id,
- "with_top_div": request.GET.get("scroll", "false") == "false"
- })
- length = len(content)
- else:
- if page_id == 1:
- content = "{0}
".format(
- _("Empty mailbox")
- )
- length = 0
- if previous_page_id is not None:
- navparams["page"] = previous_page_id
- return {"listing": content, "length": length, "pages": [page_id]}
-
-
-def render_compose(request, form, posturl, email=None, insert_signature=False):
- """Render the compose form."""
- resp = {}
- if email is None:
- body = u""
- textheader = u""
- else:
- body = email.body
- textheader = email.textheader
- if insert_signature:
- signature = EmailSignature(request.user)
- body += unicode(signature)
- randid = None
- if "id" not in request.GET:
- if "compose_mail" in request.session:
- clean_attachments(request.session["compose_mail"]["attachments"])
- randid = set_compose_session(request)
- elif "compose_mail" not in request.session \
- or request.session["compose_mail"]["id"] != request.GET["id"]:
- randid = set_compose_session(request)
-
- attachment_list = request.session["compose_mail"]["attachments"]
- if attachment_list:
- resp["menuargs"] = {"attachment_counter": len(attachment_list)}
-
- content = _render_to_string(request, "webmail/compose.html", {
- "form": form, "bodyheader": textheader,
- "body": body, "posturl": posturl
- })
-
- resp.update({
- "listing": content,
- "editor": parameters.get_user(request.user, "EDITOR")
- })
- if randid is not None:
- resp["id"] = randid
- return resp
-
-
-def compose(request):
- url = "?action=compose"
- if request.method == "POST":
- form = ComposeMailForm(request.POST)
- status, resp = send_mail(request, form, posturl=url)
- return resp
-
- form = ComposeMailForm()
- return render_compose(request, form, url, insert_signature=True)
-
-
-def get_mail_info(request):
- """Retrieve a mailbox and an email ID from a request.
- """
- mbox = request.GET.get("mbox", None)
- mailid = request.GET.get("mailid", None)
- if mbox is None or mailid is None:
- raise BadRequest(_("Invalid request"))
- return mbox, mailid
-
-
-def new_compose_form(request, action, mbox, mailid):
- """Return a new composition form.
-
- Valid for reply and forward actions only.
- """
- form = ComposeMailForm()
- modclass = globals()["%sModifier" % action.capitalize()]
- email = modclass(form, request, True, "%s:%s" % (mbox, mailid), links="1")
- url = "?action=%s&mbox=%s&mailid=%s" % (action, mbox, mailid)
- return render_compose(request, form, url, email)
-
-
-def reply(request):
- """Reply to email.
- """
- mbox, mailid = get_mail_info(request)
- if request.method == "POST":
- url = "?action=reply&mbox=%s&mailid=%s" % (mbox, mailid)
- form = ComposeMailForm(request.POST)
- status, resp = send_mail(request, form, url)
- if status:
- get_imapconnector(request).msg_answered(mbox, mailid)
- return resp
- return new_compose_form(request, "reply", mbox, mailid)
-
-
-def forward(request):
- """Forward email.
- """
- mbox, mailid = get_mail_info(request)
- if request.method == "POST":
- url = "?action=forward&mbox=%s&mailid=%s" % (mbox, mailid)
- form = ForwardMailForm(request.POST)
- status, resp = send_mail(request, form, url)
- if status:
- get_imapconnector(request).msg_forwarded(mbox, mailid)
- return resp
- return new_compose_form(request, "forward", mbox, mailid)
-
-
-@login_required
-@needs_mailbox()
-def getmailcontent(request):
- mbox = request.GET.get("mbox", None)
- mailid = request.GET.get("mailid", None)
- if mbox is None or mailid is None:
- raise BadRequest(_("Invalid request"))
- email = ImapEmail(
- request, False, "%s:%s" % (mbox, mailid), dformat="DISPLAYMODE",
- links=int(request.GET["links"])
- )
- return render(request, "common/viewmail.html", {
- "headers": email.render_headers(folder=mbox, mail_id=mailid),
- "folder": mbox, "imapid": mailid,
- "mailbody": email.body if email.body else ""
- })
-
-
-def viewmail(request):
- mbox = request.GET.get("mbox", None)
- mailid = request.GET.get("mailid", None)
- if mbox is None or mailid is None:
- raise BadRequest(_("Invalid request"))
- links = request.GET.get("links", None)
- if links is None:
- links = 1 if parameters.get_user(
- request.user, "ENABLE_LINKS") == "yes" else 0
- else:
- links = int(links)
-
- url = "{0}?mbox={1}&mailid={2}&links={3}".format(
- reverse("webmail:mailcontent_get"), mbox, mailid, links)
- content = Template("""
-
-""").render(Context({"url": url}))
-
- return dict(listing=content, menuargs=dict(mail_id=mailid))
-
-
-@login_required
-@needs_mailbox()
-def submailboxes(request):
- """Retrieve the sub mailboxes of a mailbox."""
- topmailbox = request.GET.get('topmailbox', '')
- with_unseen = request.GET.get('unseen', None)
- mboxes = get_imapconnector(request).getmboxes(
- request.user, topmailbox, unseen_messages=with_unseen == 'true')
- return render_to_json_response(mboxes)
-
-
-@login_required
-@needs_mailbox()
-def check_unseen_messages(request):
- mboxes = request.GET.get("mboxes", None)
- if not mboxes:
- raise BadRequest(_("Invalid request"))
- mboxes = mboxes.split(",")
- counters = dict()
- imapc = get_imapconnector(request)
- for mb in mboxes:
- counters[mb] = imapc.unseen_messages(mb)
- return render_to_json_response(counters)
-
-
-@login_required
-@needs_mailbox()
-def index(request):
- """Webmail actions handler
-
- Problèmes liés à la navigation 'anchor based'
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Lors d'un rafraichissemt complet, une première requête est envoyée
- vers /webmail/. On ne connait pas encore l'action qui va être
- demandée mais on peut déjà envoyer des informations indépendantes
- (comme les dossiers, le quota).
-
- Si on se contente de cela, l'affichage donnera un aspect décomposé
- qui n'est pas très séduisant (à cause de la latence notamment). Il
- faudrait pouvoir envoyer le menu par la même occasion, le souci
- étant de savoir lequel...
-
- Une solution possible : il suffirait de déplacer le menu vers la
- droite pour l'aligner avec le contenu, remonter la liste des
- dossiers (même hauteur que le menu) et renvoyer le menu en même
- temps que le contenu. Le rendu sera plus uniforme je pense.
-
- """
- action = request.GET.get("action", None)
- if action is not None:
- if action not in globals():
- raise UnknownAction
- response = globals()[action](request)
- else:
- if request.is_ajax():
- raise BadRequest(_("Invalid request"))
- response = dict(selection="webmail")
-
- curmbox = WebmailNavigationParameters(request).get("mbox", "INBOX")
- if not request.is_ajax():
- request.session["lastaction"] = None
- imapc = get_imapconnector(request)
- response["hdelimiter"] = imapc.hdelimiter
- response["mboxes"] = render_mboxes_list(request, imapc)
- imapc.getquota(curmbox)
- response["refreshrate"] = \
- int(parameters.get_user(request.user, "REFRESH_INTERVAL"))
- response["quota"] = imapc.quota_usage
- trash = parameters.get_user(request.user, "TRASH_FOLDER")
- response["trash"] = trash
- response["ro_mboxes"] = [
- "INBOX", "Junk",
- parameters.get_user(request.user, "SENT_FOLDER"),
- trash,
- parameters.get_user(request.user, "DRAFTS_FOLDER")
- ]
- response['mboxes_col_width'] = \
- int(parameters.get_user(request.user, 'MBOXES_COL_WIDTH'))
- return render(request, "webmail/index.html", response)
-
- if action in ["reply", "forward"]:
- action = "compose"
- if request.session["lastaction"] != action:
- extra_args = {}
- if "menuargs" in response:
- extra_args = response["menuargs"]
- del response["menuargs"]
- try:
- menu = getattr(webmail_tags, "%s_menu" % action)
- response["menu"] = menu("", curmbox, request.user, **extra_args)
- except KeyError:
- pass
-
- response.update(callback=action)
- http_status = 200
- if "status" in response:
- del response['status']
- http_status = 400
- return render_to_json_response(response, status=http_status)
From ec441a5c0796f54b79c6e7c19743fb501f695ff0 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Feb 2015 13:24:09 +0100
Subject: [PATCH 04/25] Remove radicale extension.
---
modoboa/extensions/radicale/__init__.py | 0
modoboa/extensions/radicale/app_settings.py | 42 ---
modoboa/extensions/radicale/factories.py | 37 ---
modoboa/extensions/radicale/forms.py | 215 --------------
.../extensions/radicale/general_callbacks.py | 38 ---
.../radicale/management/__init__.py | 0
.../radicale/management/commands/__init__.py | 0
.../management/commands/generate_rights.py | 116 --------
.../radicale/migrations/0001_initial.py | 66 -----
.../radicale/migrations/__init__.py | 0
modoboa/extensions/radicale/models.py | 165 -----------
modoboa/extensions/radicale/modo_extension.py | 33 ---
.../radicale/static/radicale/css/radicale.css | 21 --
.../static/radicale/js/jquery.dynamicrule.js | 105 -------
.../radicale/static/radicale/js/radicale.js | 125 ---------
.../templates/radicale/accessrule.html | 9 -
.../templates/radicale/calendar_detail.html | 10 -
.../templates/radicale/calendars.html | 59 ----
.../templates/radicale/calendars_page.html | 9 -
.../templates/radicale/rightsform.html | 8 -
.../radicale/templatetags/__init__.py | 0
.../radicale/templatetags/radicale_tags.py | 113 --------
modoboa/extensions/radicale/tests.py | 265 ------------------
modoboa/extensions/radicale/urls.py | 20 --
modoboa/extensions/radicale/views.py | 217 --------------
25 files changed, 1673 deletions(-)
delete mode 100644 modoboa/extensions/radicale/__init__.py
delete mode 100644 modoboa/extensions/radicale/app_settings.py
delete mode 100644 modoboa/extensions/radicale/factories.py
delete mode 100644 modoboa/extensions/radicale/forms.py
delete mode 100644 modoboa/extensions/radicale/general_callbacks.py
delete mode 100644 modoboa/extensions/radicale/management/__init__.py
delete mode 100644 modoboa/extensions/radicale/management/commands/__init__.py
delete mode 100644 modoboa/extensions/radicale/management/commands/generate_rights.py
delete mode 100644 modoboa/extensions/radicale/migrations/0001_initial.py
delete mode 100644 modoboa/extensions/radicale/migrations/__init__.py
delete mode 100644 modoboa/extensions/radicale/models.py
delete mode 100644 modoboa/extensions/radicale/modo_extension.py
delete mode 100644 modoboa/extensions/radicale/static/radicale/css/radicale.css
delete mode 100644 modoboa/extensions/radicale/static/radicale/js/jquery.dynamicrule.js
delete mode 100644 modoboa/extensions/radicale/static/radicale/js/radicale.js
delete mode 100644 modoboa/extensions/radicale/templates/radicale/accessrule.html
delete mode 100644 modoboa/extensions/radicale/templates/radicale/calendar_detail.html
delete mode 100644 modoboa/extensions/radicale/templates/radicale/calendars.html
delete mode 100644 modoboa/extensions/radicale/templates/radicale/calendars_page.html
delete mode 100644 modoboa/extensions/radicale/templates/radicale/rightsform.html
delete mode 100644 modoboa/extensions/radicale/templatetags/__init__.py
delete mode 100644 modoboa/extensions/radicale/templatetags/radicale_tags.py
delete mode 100644 modoboa/extensions/radicale/tests.py
delete mode 100644 modoboa/extensions/radicale/urls.py
delete mode 100644 modoboa/extensions/radicale/views.py
diff --git a/modoboa/extensions/radicale/__init__.py b/modoboa/extensions/radicale/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/radicale/app_settings.py b/modoboa/extensions/radicale/app_settings.py
deleted file mode 100644
index 80a6f10f8..000000000
--- a/modoboa/extensions/radicale/app_settings.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from django.utils.translation import ugettext_lazy
-from django import forms
-from modoboa.lib.parameters import AdminParametersForm
-from modoboa.lib.form_utils import SeparatorField, YesNoField
-
-
-class ParametersForm(AdminParametersForm):
- app = "radicale"
-
- server_settings = SeparatorField(
- label=ugettext_lazy("Server settings")
- )
-
- server_location = forms.CharField(
- label=ugettext_lazy("Server URL"),
- help_text=ugettext_lazy(
- "The URL of your Radicale server. "
- "It will be used to construct calendar URLs."
- ),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- rights_management_sep = SeparatorField(
- label=ugettext_lazy("Rights management"))
-
- rights_file_path = forms.CharField(
- label=ugettext_lazy("Rights file's path"),
- initial="/etc/radicale/rights",
- help_text=ugettext_lazy(
- "Path to the file that contains rights definition"
- ),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- allow_calendars_administration = YesNoField(
- label=ugettext_lazy("Allow calendars administration"),
- initial="no",
- help_text=ugettext_lazy(
- "Allow domain administrators to manage user calendars "
- "(read and write)"
- )
- )
diff --git a/modoboa/extensions/radicale/factories.py b/modoboa/extensions/radicale/factories.py
deleted file mode 100644
index 278cc3232..000000000
--- a/modoboa/extensions/radicale/factories.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""
-Fixtures factories.
-"""
-import factory
-
-from modoboa.extensions.admin.factories import (
- DomainFactory, MailboxFactory
-)
-
-from . import models
-
-
-class UserCalendarFactory(factory.DjangoModelFactory):
-
- class Meta:
- model = models.UserCalendar
-
- name = factory.Sequence(lambda n: 'User calendar %s' % n)
- mailbox = factory.SubFactory(MailboxFactory)
-
-
-class SharedCalendarFactory(factory.DjangoModelFactory):
-
- class Meta:
- model = models.SharedCalendar
-
- name = factory.Sequence(lambda n: 'Shared calendar %s' % n)
- domain = factory.SubFactory(DomainFactory)
-
-
-class AccessRuleFactory(factory.DjangoModelFactory):
-
- class Meta:
- model = models.AccessRule
-
- mailbox = factory.SubFactory(MailboxFactory)
- calendar = factory.SubFactory(UserCalendarFactory)
diff --git a/modoboa/extensions/radicale/forms.py b/modoboa/extensions/radicale/forms.py
deleted file mode 100644
index 14472ded1..000000000
--- a/modoboa/extensions/radicale/forms.py
+++ /dev/null
@@ -1,215 +0,0 @@
-"""
-Radicale extension forms.
-"""
-
-from django import forms
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.extensions.admin.models import Domain, Mailbox
-from modoboa.extensions.radicale.models import UserCalendar, SharedCalendar
-from modoboa.lib.form_utils import WizardForm, TabForms, DynamicForm
-from modoboa.lib.web_utils import render_to_json_response
-
-
-class UserCalendarForm(forms.ModelForm):
-
- """User calendar form."""
-
- class Meta:
- model = UserCalendar
- fields = ('name', 'mailbox', )
- widgets = {
- 'mailbox': forms.widgets.Select(
- attrs={
- "class": "selectpicker", "data-live-search": "true"
- }
- )
- }
-
- def __init__(self, user, *args, **kwargs):
- """Custom constructor.
-
- We need the current user to filter the mailbox list.
- """
- super(UserCalendarForm, self).__init__(*args, **kwargs)
- if user.group == 'SimpleUsers':
- del self.fields['mailbox']
- else:
- self.fields['mailbox'].queryset = \
- Mailbox.objects.get_for_admin(user)
-
-
-class SharedCalendarForm(forms.ModelForm):
-
- """Shared calendar form."""
-
- class Meta:
- model = SharedCalendar
- widgets = {
- "name": forms.TextInput(attrs={"class": "form-control"}),
- "domain": forms.widgets.Select(
- attrs={"class": "selectpicker", "data-live-search": "true"}
- )
- }
-
- def __init__(self, user, *args, **kwargs):
- """Custom constructor.
-
- We need the current user to filter the domain list.
- """
- super(SharedCalendarForm, self).__init__(*args, **kwargs)
- self.fields["domain"].queryset = Domain.objects.get_for_admin(user)
-
-
-class RightsForm(forms.Form, DynamicForm):
-
- """Rights definition form."""
-
- username = forms.CharField(
- label="", required=False, widget=forms.widgets.TextInput(
- attrs={"placeholder": ugettext_lazy("Username")}
- )
- )
- read_access = forms.BooleanField(
- initial=False, label=_("Read"), required=False
- )
- write_access = forms.BooleanField(
- initial=False, label=_("Write"), required=False
- )
-
- def __init__(self, *args, **kwargs):
- from django.http import QueryDict
-
- if "instance" in kwargs:
- self.calendar = kwargs["instance"]
- del kwargs["instance"]
- else:
- self.calendar = None
- super(RightsForm, self).__init__(*args, **kwargs)
-
- if self.calendar:
- cpt = 1
- for rule in self.calendar.rules.all():
- self._create_field(
- forms.EmailField, "username_%d" % cpt,
- rule.mailbox.full_address
- )
- self._create_field(
- forms.BooleanField, "read_access_%d" % cpt, rule.read
- )
- self._create_field(
- forms.BooleanField, "write_access_%d" % cpt, rule.write
- )
- cpt += 1
-
- if args and isinstance(args[0], QueryDict):
- self._load_from_qdict(args[0], "username", forms.EmailField)
- self._load_from_qdict(args[0], "read_access", forms.BooleanField)
- self._load_from_qdict(args[0], "write_access", forms.BooleanField)
-
- def save(self):
- """Custom save method."""
- import re
- from modoboa.lib.email_utils import split_mailbox
- from modoboa.lib.exceptions import BadRequest
- from modoboa.extensions.admin.models import Mailbox
- from .models import AccessRule
-
- usernames = {}
- for name, value in self.cleaned_data.iteritems():
- if not name.startswith("username") or not value:
- continue
- res = re.match(r"[^_]+_(\d+)$", name)
- pos = int(res.group(1)) if res else None
- usernames[value] = pos
- for rule in self.calendar.rules.select_related().all():
- if rule.mailbox.full_address not in usernames:
- rule.delete()
- for username, pos in usernames.iteritems():
- local_part, domname = split_mailbox(username)
- try:
- mbox = Mailbox.objects.get(
- address=local_part, domain__name=domname
- )
- except Mailbox.DoesNotExist:
- raise BadRequest(_("Mailbox %s does not exist"))
- if pos:
- raccess = self.cleaned_data.get("read_access_%d" % pos, False)
- waccess = self.cleaned_data.get("write_access_%d" % pos, False)
- else:
- raccess = self.cleaned_data.get("read_access", False)
- waccess = self.cleaned_data.get("write_access", False)
- acr, created = AccessRule.objects.get_or_create(
- mailbox=mbox, calendar=self.calendar
- )
- acr.read = raccess
- acr.write = waccess
- acr.save()
-
-
-class UserCalendarWizard(WizardForm):
-
- """Calendar creation wizard."""
-
- def __init__(self, request):
- super(UserCalendarWizard, self).__init__(request)
- self.add_step(UserCalendarForm, _("General"), new_args=[request.user])
- self.add_step(
- RightsForm, _("Rights"), formtpl="radicale/rightsform.html",
- )
-
- def extra_context(self, context):
- context.update({
- "title": _("New calendar"),
- "action": reverse("radicale:user_calendar_add"),
- "formid": "newcal_form"
- })
-
- def done(self):
- calendar = self.first_step.form.save(commit=False)
- if self.request.user.group == 'SimpleUsers':
- calendar.mailbox = self.request.user.mailbox_set.all()[0]
- calendar.save()
- self.steps[1].form.calendar = calendar
- self.steps[1].form.save()
- return render_to_json_response(_("Calendar created"))
-
-
-class UserCalendarEditionForm(TabForms):
-
- """User calendar edition form."""
-
- def __init__(self, request, *args, **kwargs):
- self.forms = []
- self.forms.append({
- "id": "general",
- "title": _("General"),
- "cls": UserCalendarForm,
- "mandatory": True,
- "new_args": [request.user]
- })
- self.forms.append({
- "id": "rights",
- "title": _("Rights"),
- "cls": RightsForm,
- "formtpl": "radicale/rightsform.html",
- "mandatory": True
- })
- super(UserCalendarEditionForm, self).__init__(request, *args, **kwargs)
-
- def extra_context(self, context):
- calendar = self.instances["general"]
- context.update({
- "title": self.instances["general"].name,
- "formid": "ucal_form",
- "action": reverse("radicale:user_calendar", args=[calendar.id])
- })
-
- def save(self):
- """Custom save method."""
- calendar = self.forms[0]["instance"].save()
- self.forms[1]["instance"].save()
-
- def done(self):
- return render_to_json_response(_("Calendar updated"))
diff --git a/modoboa/extensions/radicale/general_callbacks.py b/modoboa/extensions/radicale/general_callbacks.py
deleted file mode 100644
index 9cfb78938..000000000
--- a/modoboa/extensions/radicale/general_callbacks.py
+++ /dev/null
@@ -1,38 +0,0 @@
-"""
-General callbacks.
-"""
-
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext as _
-from modoboa.lib import events
-
-PERMISSIONS = [
- ("radicale", "usercalendar", "add_usercalendar"),
- ("radicale", "usercalendar", "change_usercalendar"),
- ("radicale", "usercalendar", "delete_usercalendar"),
- ("radicale", "sharedcalendar", "add_sharedcalendar"),
- ("radicale", "sharedcalendar", "change_sharedcalendar"),
- ("radicale", "sharedcalendar", "delete_sharedcalendar")
-]
-
-ROLES_PERMISSIONS = {
- "DomainAdmins": PERMISSIONS,
- "Resellers": PERMISSIONS
-}
-
-
-@events.observe("GetExtraRolePermissions")
-def extra_permissions(rolename):
- """Extra permissions."""
- return ROLES_PERMISSIONS.get(rolename, [])
-
-
-@events.observe("UserMenuDisplay")
-def top_menu(target, user):
- if target == "top_menu":
- return [
- {"name": "radicale",
- "label": _("Calendars"),
- "url": reverse('radicale:index')}
- ]
- return []
diff --git a/modoboa/extensions/radicale/management/__init__.py b/modoboa/extensions/radicale/management/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/radicale/management/commands/__init__.py b/modoboa/extensions/radicale/management/commands/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/radicale/management/commands/generate_rights.py b/modoboa/extensions/radicale/management/commands/generate_rights.py
deleted file mode 100644
index 3dd857c97..000000000
--- a/modoboa/extensions/radicale/management/commands/generate_rights.py
+++ /dev/null
@@ -1,116 +0,0 @@
-import os
-import datetime
-from optparse import make_option
-
-from django.core.management.base import BaseCommand
-
-from modoboa.core.management.commands import CloseConnectionMixin
-from modoboa.core.models import User
-from modoboa.lib import parameters
-from modoboa.extensions.admin.models import Domain
-from modoboa.extensions.radicale.models import (
- AccessRule
-)
-
-
-class Command(BaseCommand, CloseConnectionMixin):
- help = "Generate Radicale rights file"
-
- option_list = BaseCommand.option_list + (
- make_option('--force',
- action='store_true',
- default=False,
- help='Force generation of rights file'),
- )
-
- def _generate_acr(self, name, user, collection, perm="rw", comment=None):
- """Write a new access control rule to the config file.
- """
- if comment is not None:
- self._cfgfile.write("\n# %s" % comment)
- self._cfgfile.write("""
-[%s]
-user = %s
-collection = %s
-permission = %s
-""" % (name, user, collection, perm)
- )
-
- def _user_access_rules(self):
- """Create user access rules.
- """
- for acr in AccessRule.objects.select_related().all():
- section = "%s-to-%s-acr" % (
- acr.mailbox, acr.calendar
- )
- permission = ""
- if acr.read:
- permission += "r"
- if acr.write:
- permission += "w"
- self._generate_acr(
- section, acr.mailbox.full_address, acr.calendar.path,
- permission,
- )
-
- def _super_admin_rules(self):
- """Generate access rules for super administrators.
- """
- for sa in User.objects.filter(is_superuser=True):
- section = "sa-%s-acr" % sa.username
- self._generate_acr(
- section, sa.username, ".*"
- )
-
- def _domain_admin_rules(self):
- """Generate access rules for domain adminstrators.
- """
- for da in User.objects.filter(groups__name="DomainAdmins"):
- for domain in Domain.objects.get_for_admin(da):
- section = "da-%s-to-%s-acr" % (da.email, domain.name)
- self._generate_acr(
- section, da.email, "%s/user/.*" % domain.name
- )
-
- def _generate_file(self, target):
- """
- A user must not declare a rule for his direct admin!
- """
- self._cfgfile = open(target, "w")
- self._cfgfile.write("""# Rights management file for Radicale
-# This file was generated by Modoboa on %s
-# DO NOT EDIT MANUALLY!
- """ % datetime.datetime.today())
-
- allow_calendars_administration = parameters.get_admin(
- "ALLOW_CALENDARS_ADMINISTRATION", app="radicale")
- if allow_calendars_administration == "yes":
- self._super_admin_rules()
- self._domain_admin_rules()
-
- self._generate_acr(
- "domain-shared-calendars", r"^(.+)@(.+)$", r"{1}/shared/.+$",
- comment="Access rule to domain shared calendars"
- )
- self._generate_acr(
- "owners-access", r"^(.+)@(.+)$", r"{1}/user/{0}/.+$",
- comment="Read/Write permission for calendar owners"
- )
-
- self._user_access_rules()
- self._cfgfile.close()
-
- def handle(self, *args, **options):
- """Command entry point."""
- path = parameters.get_admin("RIGHTS_FILE_PATH", app="radicale")
- if not options["force"]:
- try:
- mtime = datetime.datetime.fromtimestamp(
- int(os.path.getmtime(path))
- )
- except OSError:
- pass
- else:
- if not AccessRule.objects.filter(last_update__gt=mtime).count():
- return
- self._generate_file(path)
diff --git a/modoboa/extensions/radicale/migrations/0001_initial.py b/modoboa/extensions/radicale/migrations/0001_initial.py
deleted file mode 100644
index 8654a5fc0..000000000
--- a/modoboa/extensions/radicale/migrations/0001_initial.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('admin', '0001_initial'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='AccessRule',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('read', models.BooleanField(default=False)),
- ('write', models.BooleanField(default=False)),
- ('last_update', models.DateTimeField(auto_now=True)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='SharedCalendar',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ('domain', models.ForeignKey(to='admin.Domain')),
- ],
- options={
- 'abstract': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='UserCalendar',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ('mailbox', models.ForeignKey(to='admin.Mailbox')),
- ],
- options={
- 'abstract': False,
- },
- bases=(models.Model,),
- ),
- migrations.AddField(
- model_name='accessrule',
- name='calendar',
- field=models.ForeignKey(related_name='rules', to='radicale.UserCalendar'),
- preserve_default=True,
- ),
- migrations.AddField(
- model_name='accessrule',
- name='mailbox',
- field=models.ForeignKey(to='admin.Mailbox'),
- preserve_default=True,
- ),
- migrations.AlterUniqueTogether(
- name='accessrule',
- unique_together=set([('mailbox', 'calendar')]),
- ),
- ]
diff --git a/modoboa/extensions/radicale/migrations/__init__.py b/modoboa/extensions/radicale/migrations/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/radicale/models.py b/modoboa/extensions/radicale/models.py
deleted file mode 100644
index 23c325769..000000000
--- a/modoboa/extensions/radicale/models.py
+++ /dev/null
@@ -1,165 +0,0 @@
-"""
-Radicale extension models.
-"""
-from __future__ import unicode_literals
-
-import os
-
-from django.db import models
-from django.utils.encoding import python_2_unicode_compatible
-from django.utils.translation import ugettext as _
-
-from modoboa.extensions.admin.models import Domain
-from modoboa.lib import parameters
-
-
-@python_2_unicode_compatible
-class Calendar(models.Model):
-
- """Abstract calendar definition."""
-
- name = models.CharField(max_length=200)
-
- class Meta:
- abstract = True
-
- def __str__(self):
- return self.name
-
- @property
- def path(self):
- """Return the calendar path."""
- raise NotImplementedError
-
- @property
- def url(self):
- """Return the calendar URL."""
- if not hasattr(self, "_url"):
- self._url = os.path.join(
- parameters.get_admin("SERVER_LOCATION"),
- self.path
- )
- return self._url
-
- @property
- def tags(self):
- """Return calendar tags."""
- raise NotImplementedError
-
- @property
- def owner(self):
- """Return calendar owner."""
- raise NotImplementedError
-
-
-class UserCalendarManager(models.Manager):
-
- """Custom UserCalendar manager."""
-
- def get_for_admin(self, admin):
- """Return the list of calendars this admin can access.
-
- :param ``core.User`` admin: administrator
- """
- domains = Domain.objects.get_for_admin(admin)
- return self.get_query_set().filter(mailbox__domain__in=domains)
-
-
-class UserCalendar(Calendar):
-
- """User calendar.
-
- We associate the calendar to a mailbox because we need to access
- the related domain.
-
- """
- mailbox = models.ForeignKey("admin.Mailbox")
-
- objects = UserCalendarManager()
-
- @property
- def path(self):
- """Return the calendar path.
-
- /user//
- """
- if not hasattr(self, "_path"):
- self._path = "%s/user/%s/%s" % (
- self.mailbox.domain.name, self.mailbox.address, self.name
- )
- return self._path
-
- @property
- def tags(self):
- return [{"name": "user", "label": _("User"), "type": "cal"}]
-
- @property
- def owner(self):
- return self.mailbox.user
-
-
-class SharedCalendarManager(models.Manager):
-
- """Custom SharedCalendar manager."""
-
- def get_for_admin(self, admin):
- """Return the list of calendars this admin can access.
-
- :param ``core.User`` admin: administrator
- """
- domains = Domain.objects.get_for_admin(admin)
- return self.get_query_set().filter(domain__in=domains)
-
-
-class SharedCalendar(Calendar):
-
- """Shared calendar.
-
- A shared calendar is associated to a domain and is readable and
- writable by all domain members.
-
- """
-
- domain = models.ForeignKey("admin.Domain")
-
- objects = SharedCalendarManager()
-
- @property
- def path(self):
- """Return the calendar path.
-
- /shared/
- """
- if not hasattr(self, "_path"):
- self._path = "%s/shared/%s" % (self.domain.name, self.name)
- return self._path
-
- @property
- def tags(self):
- return [{"name": "shared", "label": _("Shared"), "type": "cal"}]
-
- @property
- def owner(self):
- """Return calendar owner."""
- return self.domain
-
-
-@python_2_unicode_compatible
-class AccessRule(models.Model):
-
- """Access rules to user calendars."""
-
- mailbox = models.ForeignKey("admin.Mailbox")
- read = models.BooleanField(default=False)
- write = models.BooleanField(default=False)
- calendar = models.ForeignKey(UserCalendar, related_name="rules")
- last_update = models.DateTimeField(auto_now=True)
-
- class Meta:
- unique_together = ('mailbox', 'calendar')
-
- def __str__(self):
- access = "r" if self.read else ""
- access += "w" if self.write else ""
- return "%s access rule to %s -> " \
- % (self.mailbox, self.calendar, access if access else "no access")
diff --git a/modoboa/extensions/radicale/modo_extension.py b/modoboa/extensions/radicale/modo_extension.py
deleted file mode 100644
index 02c9fb9dc..000000000
--- a/modoboa/extensions/radicale/modo_extension.py
+++ /dev/null
@@ -1,33 +0,0 @@
-"""
-Radicale management frontend.
-
-"""
-
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.lib import parameters
-
-
-class Radicale(ModoExtension):
-
- """Radicale extension declaration."""
-
- name = "radicale"
- label = ugettext_lazy("Radicale management")
- version = "1.0"
- url = "calendars"
- description = ugettext_lazy(
- "Management frontend for Radicale, a simple calendar and contact "
- "server."
- )
-
- def load(self):
- """Plugin loading.
- """
- from .app_settings import ParametersForm
-
- parameters.register(ParametersForm, "Radicale")
- from modoboa.extensions.radicale import general_callbacks
-
-exts_pool.register_extension(Radicale)
diff --git a/modoboa/extensions/radicale/static/radicale/css/radicale.css b/modoboa/extensions/radicale/static/radicale/css/radicale.css
deleted file mode 100644
index 1be71507f..000000000
--- a/modoboa/extensions/radicale/static/radicale/css/radicale.css
+++ /dev/null
@@ -1,21 +0,0 @@
-#searchform {
- margin-bottom: 10px;
-}
-
-#original_row {
- margin-left: 100px;
-}
-
-.access-rule {
- margin-top: 5px;
- margin-left: 100px;
-}
-
-.addrule, .delrule {
- margin-left: 10px;
-}
-
-table tr td[name=actions],
-table tr th#actions {
- text-align: right;
-}
\ No newline at end of file
diff --git a/modoboa/extensions/radicale/static/radicale/js/jquery.dynamicrule.js b/modoboa/extensions/radicale/static/radicale/js/jquery.dynamicrule.js
deleted file mode 100644
index cf94de18c..000000000
--- a/modoboa/extensions/radicale/static/radicale/js/jquery.dynamicrule.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * @module jquery.dynamicrule
- */
-
-(function($) {
- var DynamicRule = function(element, options) {
- this.initialize(element, options);
- };
-
- DynamicRule.prototype = {
- constructor: DynamicRule,
-
- /**
- * Creates an instance of DynamicRule.
- *
- * @constructor
- * @this {DynamicRule}
- * @param {object} element -
- * @param {dictionary} options - instance options
- */
- initialize: function(element, options) {
- this.$element = $(element);
- this.options = $.extend({}, $.fn.dynamicrule.defaults, options);
- this.rules_counter = 1;
-
- $(document).on(
- "click", "a[class=addrule]", $.proxy(this.add_rule, this)
- );
- $(document).on(
- "click", "a[class=delrule]", $.proxy(this.delete_rule, this)
- );
- },
-
- /**
- * Reset the current rule to default values.
- */
- reset_original_rule: function() {
- this.$element.find("#id_username").prop("value", "");
- this.$element.find("#id_read_access").prop("checked", "");
- this.$element.find("#id_write_access").prop("checked", "");
- },
-
- /**
- * Save the current rule to a new set of elements and reset
- * the original ones.
- */
- add_rule: function(event) {
- var rulename = $("#id_username").prop("value");
-
- event.preventDefault();
- if (rulename === "") {
- return;
- }
- var $clone = this.$element.clone();
- var $btn = $clone.find("a");
-
- $clone.attr("id", "");
- $btn.find("span").removeClass("fa-plus").addClass("fa-trash");
- $btn.removeClass("addrule").addClass("delrule");
- $clone.find("#id_username")
- .attr("id", "id_username_" + this.rules_counter)
- .attr("name", "username_" + this.rules_counter);
- $clone.find("#id_read_access")
- .attr("id", "id_read_access_" + this.rules_counter)
- .attr("name", "read_access_" + this.rules_counter);
- $clone.find("#id_write_access")
- .attr("id", "id_write_access_" + this.rules_counter)
- .attr("name", "write_access_" + this.rules_counter);
- $clone.insertAfter(this.$element);
- this.rules_counter++;
- this.reset_original_rule();
- },
-
- /**
- * Delete a given rule.
- *
- * @param {object} event - event object
- */
- delete_rule: function(event) {
- event.preventDefault();
- var $link = get_target(event, "a");
-
- $link.parent().remove();
- }
- };
-
- $.fn.dynamicrule = function(method) {
- return this.each(function() {
- var $this = $(this),
- data = $this.data('dynamicrule'),
- options = typeof method === "object" && method;
-
- if (!data) {
- $this.data('dynamicrule', new DynamicRule(this, options));
- }
- if (typeof method === "string") {
- data[method]();
- }
- });
- };
-
- $.fn.dynamicrule.defaults = {
- };
-
-})(jQuery);
diff --git a/modoboa/extensions/radicale/static/radicale/js/radicale.js b/modoboa/extensions/radicale/static/radicale/js/radicale.js
deleted file mode 100644
index a38393bcc..000000000
--- a/modoboa/extensions/radicale/static/radicale/js/radicale.js
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
- * Creates an instance of Radicale.
- *
- * @constructor
- * @param {Object} options - instance options
- * @classdesc This class contains a set of methods used by the
- * Radicale application.
- */
-var Radicale = function(options) {
- Listing.call(this, options);
-};
-
-Radicale.prototype = {
- constructor: Radicale,
-
- defaults: {
- deflocation: "list/",
- main_table_id: "calendar_table",
- eor_message: gettext("No more calendar to show")
- },
-
- initialize: function(options) {
- this.options = $.extend({}, this.defaults, options);
- this.options.defcallback = $.proxy(this.list_cb, this);
- Listing.prototype.initialize.call(this, this.options);
- this.options.navigation_params.push("calfilter");
- this.register_tag_handler("cal", this.generic_tag_handler);
- $(document).on(
- "click", "a[name=delcalendar]", $.proxy(this.del_calendar, this)
- );
- },
-
- list_cb: function(data) {
- $("#{0} tbody".format(this.options.main_table_id)).html(data.rows);
- this.update_listing(data);
- },
-
- /**
- * Refresh the listing.
- *
- * @this Radicale
- * @param {Object} data - the ajax call response (JSON)
- */
- reload_listing: function(data) {
- this.navobj.update(true);
- if (data) {
- $("body").notify("success", data, 2000);
- }
- },
-
- /**
- * Rights form initialization.
- *
- * @this Radicale
- */
- rightsform_init: function() {
- $("#original_row").dynamicrule();
- $("#id_username").autocompleter({
- choices: $.proxy(this.get_username_list, this)
- });
- },
-
- add_calendar_cb: function() {
- this.rightsform_init();
- $("#wizard").cwizard({
- formid: "newcal_form",
- success_callback: $.proxy(this.reload_listing, this)
- });
- },
-
- /**
- * Retrieve a list of username from the server.
- */
- get_username_list: function() {
- var result;
-
- $.ajax({
- url: this.options.username_list_url,
- dataType: "json",
- async: false
- }).done(function(data) {
- result = data;
- });
- return result;
- },
-
- edit_calendar_cb: function() {
- this.rightsform_init();
- $('.submit').on('click', $.proxy(function(e) {
- simple_ajax_form_post(e, {
- formid: "ucal_form",
- reload_on_success: false,
- success_cb: $.proxy(this.reload_listing, this)
- });
- }, this));
- },
-
- shared_calendar_cb: function() {
- $('.submit').on('click', $.proxy(function(e) {
- simple_ajax_form_post(e, {
- formid: "sharedcal_form",
- reload_on_success: false,
- success_cb: $.proxy(this.reload_listing, this)
- });
- }, this));
- },
-
- /**
- * Delete a user calendar.
- */
- del_calendar: function(event) {
- event.preventDefault();
- var $link = get_target(event, "a");
-
- if (!confirm($link.attr("title"))) {
- return;
- }
- $.ajax({
- url: $link.attr("href"),
- type: "DELETE"
- }).done($.proxy(this.reload_listing, this));
- }
-};
-
-Radicale.prototype = $.extend({}, Listing.prototype, Radicale.prototype);
diff --git a/modoboa/extensions/radicale/templates/radicale/accessrule.html b/modoboa/extensions/radicale/templates/radicale/accessrule.html
deleted file mode 100644
index 5ac132826..000000000
--- a/modoboa/extensions/radicale/templates/radicale/accessrule.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% load i18n %}
-{% load form_tags %}
-
-
diff --git a/modoboa/extensions/radicale/templates/radicale/calendar_detail.html b/modoboa/extensions/radicale/templates/radicale/calendar_detail.html
deleted file mode 100644
index b5d5f2cb2..000000000
--- a/modoboa/extensions/radicale/templates/radicale/calendar_detail.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% extends "common/generic_modal.html" %}
-
-{% load i18n %}
-
-{% block modalbody %}
-{% trans "To access this calendar, use the following address:" %}
-
-{% endblock %}
diff --git a/modoboa/extensions/radicale/templates/radicale/calendars.html b/modoboa/extensions/radicale/templates/radicale/calendars.html
deleted file mode 100644
index c127ce396..000000000
--- a/modoboa/extensions/radicale/templates/radicale/calendars.html
+++ /dev/null
@@ -1,59 +0,0 @@
-{% extends "twocols.html" %}
-{% load i18n radicale_tags %}
-{% load static %}
-
-{% block extra_css %}
-
-
-{% endblock %}
-
-{% block extra_js %}
-
-
-
-
-
-
-
-
-
-{% endblock %}
-
-{% block leftcol %}
-
-{% endblock %}
-
-{% block apparea %}
-
-
- {% include "admin/searchform.html" %}
-
-
-
-
-
-
-
-
-
- {% trans "Name" %}
- {% if with_owner %}{% trans "Owner" %} {% endif %}
- {% trans "Tags" %}
- {% trans "Actions" %}
-
-
-
-
-
-
-
-{% endblock %}
diff --git a/modoboa/extensions/radicale/templates/radicale/calendars_page.html b/modoboa/extensions/radicale/templates/radicale/calendars_page.html
deleted file mode 100644
index cbe0dbe4e..000000000
--- a/modoboa/extensions/radicale/templates/radicale/calendars_page.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% load i18n lib_tags radicale_tags %}
-{% for cal in calendars %}
-
- {% calendar_view_link cal %}
- {% if with_owner %}{{ cal.owner }} {% endif %}
- {% render_tags cal.tags %}
- {% calendar_actions cal %}
-
-{% endfor %}
diff --git a/modoboa/extensions/radicale/templates/radicale/rightsform.html b/modoboa/extensions/radicale/templates/radicale/rightsform.html
deleted file mode 100644
index 6248509f6..000000000
--- a/modoboa/extensions/radicale/templates/radicale/rightsform.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% load form_tags radicale_tags %}
-
-{% render_rule_fields form %}
diff --git a/modoboa/extensions/radicale/templatetags/__init__.py b/modoboa/extensions/radicale/templatetags/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/radicale/templatetags/radicale_tags.py b/modoboa/extensions/radicale/templatetags/radicale_tags.py
deleted file mode 100644
index 83bc07994..000000000
--- a/modoboa/extensions/radicale/templatetags/radicale_tags.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""
-Custom template tags.
-"""
-from django import template
-from django.core.urlresolvers import reverse
-from django.template.loader import render_to_string
-from django.utils.translation import ugettext as _
-
-from modoboa.lib.templatetags.lib_tags import render_link
-from modoboa.lib.web_utils import render_actions
-
-
-register = template.Library()
-
-
-@register.simple_tag
-def radicale_left_menu(user):
- """Menu located inside the left column.
-
- :param ``User`` user: current user
- :rtype: string
- :return: the menu rendered as HTML code
- """
- entries = [
- {"name": "newusercalendar",
- "label": _("Add calendar"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "radicale.add_calendar_cb",
- "url": reverse("radicale:user_calendar_add")},
- ]
- if user.group != "SimpleUsers":
- entries += [
- {"name": "newsharedcalendar",
- "label": _("Add shared calendar"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "radicale.shared_calendar_cb",
- "url": reverse("radicale:shared_calendar_add")},
- ]
- return render_to_string('common/menulist.html', {
- "entries": entries,
- "user": user
- })
-
-
-@register.simple_tag
-def calendar_view_link(calendar):
- """Render a link to view calendar detail."""
- linkdef = {
- "label": calendar.name, "modal": True,
- "title": _("View calendar detail")
- }
- if calendar.__class__.__name__ == "UserCalendar":
- linkdef["url"] = reverse(
- "radicale:user_calendar_detail", args=[calendar.pk]
- )
- else:
- linkdef["url"] = reverse(
- "radicale:shared_calendar_detail", args=[calendar.pk]
- )
- return render_link(linkdef)
-
-
-@register.simple_tag
-def calendar_actions(calendar):
- """Render per-calendar actions."""
- actions = [
- {"name": "editcalendar",
- "title": _("Edit %s" % calendar),
- "modal": True,
- "img": "fa fa-edit"},
- {"name": "delcalendar",
- "title": _("Delete %s?" % calendar),
- "img": "fa fa-trash"}
- ]
- if calendar.__class__.__name__ == 'UserCalendar':
- actions[0]["url"] = reverse(
- "radicale:user_calendar", args=[calendar.pk])
- actions[0]["modalcb"] = "radicale.edit_calendar_cb"
- actions[1]["url"] = reverse(
- "radicale:user_calendar", args=[calendar.id])
- else:
- actions[0]["url"] = reverse(
- "radicale:shared_calendar", args=[calendar.pk])
- actions[0]["modalcb"] = "radicale.shared_calendar_cb"
- actions[1]["url"] = reverse(
- "radicale:shared_calendar", args=[calendar.id])
- return render_actions(actions)
-
-
-@register.simple_tag
-def render_rule_fields(form):
- """Render access rules for a given calendar."""
- from django.forms import forms
-
- cpt = 1
- result = ""
- while True:
- fname = "username_%d" % cpt
- if fname not in form.fields:
- break
- rfieldname = "read_access_%d" % cpt
- wfieldname = "write_access_%d" % cpt
- result += render_to_string('radicale/accessrule.html', {
- "username": forms.BoundField(form, form.fields[fname], fname),
- "read_access": forms.BoundField(
- form, form.fields[rfieldname], rfieldname),
- "write_access": forms.BoundField(
- form, form.fields[wfieldname], wfieldname)
- })
- cpt += 1
- return result
diff --git a/modoboa/extensions/radicale/tests.py b/modoboa/extensions/radicale/tests.py
deleted file mode 100644
index 749364d3c..000000000
--- a/modoboa/extensions/radicale/tests.py
+++ /dev/null
@@ -1,265 +0,0 @@
-"""
-Radicale extension unit tests.
-"""
-import os
-import tempfile
-from ConfigParser import SafeConfigParser
-
-from django.core.exceptions import ObjectDoesNotExist
-from django.core.urlresolvers import reverse
-from django.core import management
-
-from modoboa.lib import parameters
-from modoboa.lib.tests import ModoTestCase
-from modoboa.extensions.admin.factories import (
- MailboxFactory, populate_database
-)
-from modoboa.extensions.admin.models import (
- Domain, Mailbox
-)
-
-from .factories import (
- UserCalendarFactory, SharedCalendarFactory, AccessRuleFactory
-)
-from .models import UserCalendar, SharedCalendar, AccessRule
-
-
-class UserCalendarTestCase(ModoTestCase):
-
- def setUp(self):
- super(UserCalendarTestCase, self).setUp()
- populate_database()
-
- def assertRuleEqual(self, calname, username, read=False, write=False):
- acr = AccessRule.objects.get(
- mailbox__user__username=username,
- calendar__name=calname)
- self.assertEqual(acr.read, read)
- self.assertEqual(acr.write, write)
-
- def test_add_calendar(self):
- MailboxFactory(
- address="polo", domain__name="test.com",
- user__username="polo@test.com")
-
- # As a super administrator
- mbox = Mailbox.objects.get(address='user', domain__name='test.com')
- values = {
- "name": "Test calendar",
- "mailbox": mbox.pk,
- "username": "admin@test.com",
- "read_access": 1,
- "stepid": "step2"
- }
- self.ajax_post(
- reverse("radicale:user_calendar_add"), values)
- self.clt.logout()
- self.assertRuleEqual("Test calendar", "admin@test.com", read=True)
-
- # As a domain administrator
- self.clt.login(username="admin@test.com", password="toto")
- values = {
- "name": "Test calendar 2",
- "mailbox": mbox.pk,
- "username": "admin@test.com",
- "read_access": 1,
- "write_access": 1,
- "stepid": "step2"
- }
- self.ajax_post(
- reverse("radicale:user_calendar_add"), values)
- self.clt.logout()
- self.assertRuleEqual(
- "Test calendar 2", "admin@test.com", read=True, write=True
- )
-
- # As a user
- self.clt.login(username="user@test.com", password="toto")
- values = {
- "name": "My calendar",
- "username": "admin@test.com",
- "read_access": 1,
- "write_access": 1,
- "username_1": "polo@test.com",
- "write_access_1": 1,
- "stepid": "step2"
- }
- self.ajax_post(
- reverse("radicale:user_calendar_add"), values)
- UserCalendar.objects.get(name="My calendar")
- self.assertRuleEqual(
- "My calendar", "admin@test.com", read=True, write=True)
- self.assertRuleEqual("My calendar", "polo@test.com", write=True)
-
- def test_edit_calendar(self):
- cal = UserCalendarFactory(
- mailbox__user__username='test@modoboa.org',
- mailbox__address='test', mailbox__domain__name='modoboa.org')
- values = {
- "name": "Modified", "mailbox": cal.mailbox.pk
- }
- self.ajax_post(
- reverse("radicale:user_calendar", args=[cal.pk]), values
- )
-
- def test_del_calendar(self):
- cal = UserCalendarFactory(
- mailbox__user__username='test@modoboa.org',
- mailbox__address='test', mailbox__domain__name='modoboa.org')
- self.ajax_delete(
- reverse("radicale:user_calendar", args=[cal.pk])
- )
- with self.assertRaises(ObjectDoesNotExist):
- UserCalendar.objects.get(pk=cal.pk)
-
- def test_del_calendar_denied(self):
- cal = UserCalendarFactory(
- mailbox__user__username='test@modoboa.org',
- mailbox__address='test', mailbox__domain__name='modoboa.org')
- self.clt.logout()
- self.clt.login(username="admin@test.com", password="toto")
- self.ajax_delete(
- reverse("radicale:user_calendar", args=[cal.pk]), status=403
- )
-
- def test_add_calendar_denied(self):
- self.clt.logout()
- self.clt.login(username="admin@test.com", password="toto")
- values = {
- "name": "Test calendar",
- "mailbox": Mailbox.objects.get(
- address="user", domain__name="test2.com").pk,
- "stepid": "step2"
- }
- self.ajax_post(
- reverse("radicale:user_calendar_add"), values, status=400)
-
-
-class SharedCalendarTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(SharedCalendarTestCase, self).setUp()
- populate_database()
-
- def test_add_calendar(self):
- # As a super administrator
- domain = Domain.objects.get(name="test.com")
- values = {
- "name": "Test calendar",
- "domain": domain.pk,
- }
- self.ajax_post(
- reverse("radicale:shared_calendar_add"), values)
- self.clt.logout()
-
- # As a domain administrator
- self.clt.login(username="admin@test.com", password="toto")
- values = {
- "name": "Test calendar 2",
- "domain": domain.pk
- }
- self.ajax_post(
- reverse("radicale:shared_calendar_add"), values)
- self.clt.logout()
-
- def test_add_calendar_denied(self):
- self.clt.logout()
- self.clt.login(username="admin@test.com", password="toto")
- values = {
- "name": "Test calendar",
- "domain": Domain.objects.get(name="test2.com")
- }
- self.ajax_post(
- reverse("radicale:shared_calendar_add"), values, status=400)
-
- def test_edit_calendar(self):
- cal = SharedCalendarFactory(
- domain__name='modoboa.org')
- values = {
- "name": "Modified", "domain": cal.domain.pk
- }
- self.ajax_post(
- reverse("radicale:shared_calendar", args=[cal.pk]), values
- )
- cal = SharedCalendar.objects.get(pk=cal.pk)
- self.assertEqual(cal.name, "Modified")
-
- def test_del_calendar(self):
- cal = SharedCalendarFactory(domain__name='modoboa.org')
- self.ajax_delete(
- reverse("radicale:shared_calendar", args=[cal.pk])
- )
- with self.assertRaises(ObjectDoesNotExist):
- SharedCalendar.objects.get(pk=cal.pk)
-
- def test_del_calendar_denied(self):
- cal = SharedCalendarFactory(domain__name='modoboa.org')
- self.clt.logout()
- self.clt.login(username="admin@test.com", password="toto")
- self.ajax_delete(
- reverse("radicale:shared_calendar", args=[cal.pk]), status=403
- )
-
-
-class AccessRuleTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(AccessRuleTestCase, self).setUp()
- populate_database()
- self.rights_file_path = tempfile.mktemp()
- parameters.save_admin(
- "RIGHTS_FILE_PATH", self.rights_file_path, app="radicale")
-
- def tearDown(self):
- os.unlink(self.rights_file_path)
-
- def test_rights_file_generation(self):
- mbox = Mailbox.objects.get(address="admin", domain__name="test.com")
- cal = UserCalendarFactory(mailbox=mbox)
-
- AccessRuleFactory(
- mailbox=Mailbox.objects.get(
- address="user", domain__name="test.com"),
- calendar=cal, read=True)
- management.call_command("generate_rights", verbosity=False)
-
- cfg = SafeConfigParser()
- with open(self.rights_file_path) as fpo:
- cfg.readfp(fpo)
-
- # Check mandatory rules
- self.assertTrue(cfg.has_section("domain-shared-calendars"))
- self.assertTrue(cfg.has_section("owners-access"))
-
- # Check user-defined rules
- section = "user@test.com-to-User calendar 1-acr"
- self.assertTrue(cfg.has_section(section))
- self.assertEqual(cfg.get(section, "user"), "user@test.com")
- self.assertEqual(
- cfg.get(section, "collection"),
- "test.com/user/admin/User calendar 1"
- )
- self.assertEqual(cfg.get(section, "permission"), "r")
-
- def test_rights_file_generation_with_admin(self):
- parameters.save_admin(
- "ALLOW_CALENDARS_ADMINISTRATION", "yes", app="radicale")
- management.call_command("generate_rights", verbosity=False)
- cfg = SafeConfigParser()
- with open(self.rights_file_path) as fpo:
- cfg.readfp(fpo)
-
- # Check mandatory rules
- self.assertTrue(cfg.has_section("domain-shared-calendars"))
- self.assertTrue(cfg.has_section("owners-access"))
-
- # Super admin rules
- section = "sa-admin-acr"
- self.assertTrue(cfg.has_section(section))
-
- # Domain admin rules
- for section in ["da-admin@test.com-to-test.com-acr",
- "da-admin@test2.com-to-test2.com-acr"]:
- self.assertTrue(cfg.has_section(section))
diff --git a/modoboa/extensions/radicale/urls.py b/modoboa/extensions/radicale/urls.py
deleted file mode 100644
index 6ae2542f6..000000000
--- a/modoboa/extensions/radicale/urls.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from django.conf.urls import url, patterns
-
-urlpatterns = patterns(
- 'modoboa.extensions.radicale.views',
-
- url(r'^$', 'index', name="index"),
- url(r'^list/$', 'calendars_page', name="calendars_page"),
- url(r'^user/$', 'new_user_calendar', name='user_calendar_add'),
- url(r'^user/(?P\d+)/$', 'user_calendar',
- name='user_calendar'),
- url(r'^user/(?P\d+)/detail/$', 'user_calendar_detail',
- name='user_calendar_detail'),
- url(r'^shared/$', 'new_shared_calendar',
- name='shared_calendar_add'),
- url(r'^shared/(?P\d+)/$', 'shared_calendar',
- name='shared_calendar'),
- url(r'^shared/(?P\d+)/detail/$', 'shared_calendar_detail',
- name='shared_calendar_detail'),
- url(r'^usernames/$', 'username_list', name='username_list'),
-)
diff --git a/modoboa/extensions/radicale/views.py b/modoboa/extensions/radicale/views.py
deleted file mode 100644
index 619c41dde..000000000
--- a/modoboa/extensions/radicale/views.py
+++ /dev/null
@@ -1,217 +0,0 @@
-"""
-Radicale extension views.
-"""
-from itertools import chain
-
-from django.shortcuts import render
-from django.core.urlresolvers import reverse
-from django.contrib.auth.decorators import (
- login_required, permission_required, user_passes_test
-)
-from django.utils.translation import ugettext as _
-
-from modoboa.lib.listing import get_sort_order, get_listing_page
-from modoboa.lib.web_utils import (
- _render_to_string, render_to_json_response
-)
-from modoboa.lib.exceptions import NotFound, PermDeniedException
-
-from modoboa.extensions.radicale.forms import (
- UserCalendarWizard, SharedCalendarForm, UserCalendarEditionForm
-)
-from modoboa.extensions.radicale.models import UserCalendar, SharedCalendar
-
-
-@login_required
-def index(request):
- """Calendar list entry point."""
- return render(request, "radicale/calendars.html", {
- "selection": "radicale",
- "with_owner": request.user.group != "SimpleUsers"
- })
-
-
-def get_calendar_page(request, page_id=None):
- """Return a page containing calendars."""
- sort_order, sort_dir = get_sort_order(request.GET, "name")
- calfilter = request.GET.get("calfilter", None)
- searchquery = request.GET.get("searchquery", None)
- page_id = request.GET.get("page", 1)
- if request.user.group == "SimpleUsers":
- mbox = request.user.mailbox_set.all()[0]
- cals = UserCalendar.objects.filter(mailbox=mbox)
- if searchquery is not None:
- cals = cals.filter(name__icontains=searchquery)
- cals = cals.select_related().all()
- else:
- ucals = []
- if calfilter is None or calfilter == "user":
- ucals = UserCalendar.objects.get_for_admin(request.user)
- if searchquery is not None:
- ucals = ucals.filter(name__icontains=searchquery)
- scals = []
- if calfilter is None or calfilter == "shared":
- scals = SharedCalendar.objects.get_for_admin(request.user)
- if searchquery is not None:
- scals = scals.filter(name__icontains=searchquery)
- cals = chain(ucals, scals)
- cals = sorted(
- cals, key=lambda c: getattr(c, sort_order), reverse=sort_dir == '-'
- )
- return get_listing_page(cals, page_id)
-
-
-@login_required
-def calendars_page(request, tplname="radicale/calendars_page.html"):
- """Return a page of calendars.
-
- The content depends on current user's role.
- """
- page = get_calendar_page(request)
- if page is None:
- context = {"length": 0}
- else:
- context = {
- "rows": _render_to_string(request, tplname, {
- "calendars": page.object_list,
- "with_owner": request.user.group != "SimpleUsers"
- }),
- "page": page.number
- }
- return render_to_json_response(context)
-
-
-@login_required
-def new_user_calendar(request):
- """Calendar creation view.
- """
- return UserCalendarWizard(request).process()
-
-
-@login_required
-def user_calendar(request, pk):
- """Edit or remove a calendar."""
- try:
- ucal = UserCalendar.objects.select_related().get(pk=pk)
- except UserCalendar.DoesNotExist:
- raise NotFound
- if request.user != ucal.mailbox.user and \
- not request.user.can_access(ucal.mailbox.domain):
- raise PermDeniedException
- instances = {"general": ucal, "rights": ucal}
- if request.method == "DELETE":
- ucal.delete()
- return render_to_json_response(_("Calendar removed"))
- return UserCalendarEditionForm(request, instances=instances).process()
-
-
-@login_required
-def user_calendar_detail(request, pk):
- """Display user calendar's detail."""
- try:
- ucal = UserCalendar.objects.select_related().get(pk=pk)
- except UserCalendar.DoesNotExist:
- raise NotFound
- if request.user != ucal.mailbox.user and \
- not request.user.can_access(ucal.mailbox.domain):
- raise PermDeniedException
- return render(request, "radicale/calendar_detail.html", {
- "title": ucal.name, "calendar": ucal
- })
-
-
-@login_required
-@permission_required("radicale.add_sharedcalendar")
-def new_shared_calendar(request):
- """Shared calendar creation view."""
- if request.method == "POST":
- form = SharedCalendarForm(request.user, request.POST)
- if form.is_valid():
- form.save()
- return render_to_json_response(_("Calendar created"))
- return render_to_json_response(
- {"form_errors": form.errors}, status=400
- )
- form = SharedCalendarForm(request.user)
- return render(request, "common/generic_modal_form.html", {
- "form": form,
- "formid": "sharedcal_form",
- "title": _("New shared calendar"),
- "action": reverse("radicale:shared_calendar_add"),
- "action_classes": "submit",
- "action_label": _("Submit")
- })
-
-
-@login_required
-@user_passes_test(
- lambda u: u.has_perm("radicale.change_sharedcalendar")
- or u.has_perm("radicale.delete_sharedcalendar")
-)
-def shared_calendar(request, pk):
- """Edit or remove a shared calendar."""
- try:
- scal = SharedCalendar.objects.select_related().get(pk=pk)
- except SharedCalendar.DoesNotExist:
- raise NotFound
- if not request.user.can_access(scal.domain):
- raise PermDeniedException
- if request.method == "DELETE":
- if not request.user.can_access(scal.domain):
- raise PermDeniedException
- scal.delete()
- return render_to_json_response(_("Calendar removed"))
- if request.method == "POST":
- form = SharedCalendarForm(request.user, request.POST, instance=scal)
- if form.is_valid():
- form.save()
- return render_to_json_response(_("Calendar updated"))
- return render_to_json_response(
- {"form_errors": form.errors}, status=400
- )
- form = SharedCalendarForm(request.user, instance=scal)
- return render(request, "common/generic_modal_form.html", {
- "form": form,
- "formid": "sharedcal_form",
- "title": scal.name,
- "action": reverse("radicale:shared_calendar", args=[scal.pk]),
- "action_classes": "submit",
- "action_label": _("Submit")
- })
-
-
-@login_required
-@user_passes_test(
- lambda u: u.has_perm("radicale.change_sharedcalendar")
-)
-def shared_calendar_detail(request, pk):
- """Display shared calendar's detail."""
- try:
- scal = SharedCalendar.objects.select_related().get(pk=pk)
- except SharedCalendar.DoesNotExist:
- raise NotFound
- if not request.user.can_access(scal.domain):
- raise PermDeniedException
- return render(request, "radicale/calendar_detail.html", {
- "title": scal.name, "calendar": scal
- })
-
-
-@login_required
-def username_list(request):
- """Get the list of username the current user can see.
- """
- from modoboa.extensions.admin.models import Domain, Mailbox
-
- result = []
- qset = Mailbox.objects.select_related("user")
- if request.user.has_perm("admin.add_mailbox"):
- qset = qset.filter(
- domain__in=Domain.objects.get_for_admin(request.user)
- )
- else:
- user_domain = request.user.mailbox_set.all()[0].domain
- qset = qset.filter(domain=user_domain)
- for mbox in qset:
- result.append(mbox.user.username)
- return render_to_json_response(result)
From 704a046b5bb236f8b2adbef6a7696da4697bbc78 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Feb 2015 13:39:40 +0100
Subject: [PATCH 05/25] Remove limits extension.
---
modoboa/extensions/limits/__init__.py | 0
modoboa/extensions/limits/app_settings.py | 55 ---
modoboa/extensions/limits/controls.py | 219 ----------
modoboa/extensions/limits/fixtures/demo.json | 1 -
modoboa/extensions/limits/forms.py | 91 ----
.../extensions/limits/general_callbacks.py | 123 ------
modoboa/extensions/limits/lib.py | 53 ---
.../limits/migrations/0001_initial.py | 47 ---
.../extensions/limits/migrations/__init__.py | 0
modoboa/extensions/limits/models.py | 148 -------
modoboa/extensions/limits/modo_extension.py | 44 --
.../limits/templates/limits/poolusage.html | 12 -
modoboa/extensions/limits/tests.py | 394 ------------------
modoboa/extensions/limits/urls.py | 6 -
modoboa/extensions/limits/views.py | 1 -
modoboa/extensions/stats/__init__.py | 0
modoboa/extensions/stats/app_settings.py | 25 --
modoboa/extensions/stats/general_callbacks.py | 22 -
modoboa/extensions/stats/graphics.py | 161 -------
modoboa/extensions/stats/lib.py | 24 --
.../extensions/stats/management/__init__.py | 0
.../stats/management/commands/__init__.py | 0
.../stats/management/commands/logparser.py | 378 -----------------
modoboa/extensions/stats/modo_extension.py | 35 --
.../stats/static/stats/css/stats.css | 71 ----
.../stats/static/stats/js/d3.legend.js | 70 ----
.../stats/static/stats/js/graphic.js | 344 ---------------
.../extensions/stats/static/stats/js/stats.js | 176 --------
.../stats/templates/stats/index.html | 89 ----
modoboa/extensions/stats/urls.py | 10 -
modoboa/extensions/stats/views.py | 134 ------
31 files changed, 2733 deletions(-)
delete mode 100644 modoboa/extensions/limits/__init__.py
delete mode 100644 modoboa/extensions/limits/app_settings.py
delete mode 100644 modoboa/extensions/limits/controls.py
delete mode 100644 modoboa/extensions/limits/fixtures/demo.json
delete mode 100644 modoboa/extensions/limits/forms.py
delete mode 100644 modoboa/extensions/limits/general_callbacks.py
delete mode 100644 modoboa/extensions/limits/lib.py
delete mode 100644 modoboa/extensions/limits/migrations/0001_initial.py
delete mode 100644 modoboa/extensions/limits/migrations/__init__.py
delete mode 100644 modoboa/extensions/limits/models.py
delete mode 100644 modoboa/extensions/limits/modo_extension.py
delete mode 100644 modoboa/extensions/limits/templates/limits/poolusage.html
delete mode 100644 modoboa/extensions/limits/tests.py
delete mode 100644 modoboa/extensions/limits/urls.py
delete mode 100644 modoboa/extensions/limits/views.py
delete mode 100644 modoboa/extensions/stats/__init__.py
delete mode 100644 modoboa/extensions/stats/app_settings.py
delete mode 100644 modoboa/extensions/stats/general_callbacks.py
delete mode 100644 modoboa/extensions/stats/graphics.py
delete mode 100644 modoboa/extensions/stats/lib.py
delete mode 100644 modoboa/extensions/stats/management/__init__.py
delete mode 100644 modoboa/extensions/stats/management/commands/__init__.py
delete mode 100644 modoboa/extensions/stats/management/commands/logparser.py
delete mode 100644 modoboa/extensions/stats/modo_extension.py
delete mode 100644 modoboa/extensions/stats/static/stats/css/stats.css
delete mode 100644 modoboa/extensions/stats/static/stats/js/d3.legend.js
delete mode 100644 modoboa/extensions/stats/static/stats/js/graphic.js
delete mode 100644 modoboa/extensions/stats/static/stats/js/stats.js
delete mode 100644 modoboa/extensions/stats/templates/stats/index.html
delete mode 100644 modoboa/extensions/stats/urls.py
delete mode 100644 modoboa/extensions/stats/views.py
diff --git a/modoboa/extensions/limits/__init__.py b/modoboa/extensions/limits/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/limits/app_settings.py b/modoboa/extensions/limits/app_settings.py
deleted file mode 100644
index 2d759a3cd..000000000
--- a/modoboa/extensions/limits/app_settings.py
+++ /dev/null
@@ -1,55 +0,0 @@
-"""Custom settings."""
-
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-
-from modoboa.lib.form_utils import SeparatorField
-from modoboa.lib.parameters import AdminParametersForm
-
-
-class ParametersForm(AdminParametersForm):
- app = "limits"
-
- defv_sep = SeparatorField(label=_("Default limits"))
-
- deflt_domain_admins_limit = forms.IntegerField(
- label=_("Domain admins"),
- initial=0,
- help_text=_(
- "Maximum number of allowed domain administrators for a new "
- "administrator"
- ),
- widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"})
- )
- deflt_domains_limit = forms.IntegerField(
- label=_("Domains"),
- initial=0,
- help_text=_(
- "Maximum number of allowed domains for a new administrator"),
- widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"})
- )
- deflt_domain_aliases_limit = forms.IntegerField(
- label=_("Domain aliases"),
- initial=0,
- help_text=_(
- "Maximum number of allowed domain aliases for a new administrator"),
- widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"})
- )
- deflt_mailboxes_limit = forms.IntegerField(
- label=_("Mailboxes"),
- initial=0,
- help_text=_(
- "Maximum number of allowed mailboxes for a new administrator"),
- widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"})
- )
- deflt_mailbox_aliases_limit = forms.IntegerField(
- label=_("Mailbox aliases"),
- initial=0,
- help_text=_(
- "Maximum number of allowed aliases for a new administrator"),
- widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"})
- )
-
- def __init__(self, *args, **kwargs):
- super(AdminParametersForm, self).__init__(*args, **kwargs)
- self._load_extra_parameters('A')
diff --git a/modoboa/extensions/limits/controls.py b/modoboa/extensions/limits/controls.py
deleted file mode 100644
index f5d00b4ac..000000000
--- a/modoboa/extensions/limits/controls.py
+++ /dev/null
@@ -1,219 +0,0 @@
-# coding: utf-8
-"""
-:mod:`controls` --- provides event handlers that check if limits are reached
-----------------------------------------------------------------------------
-
-"""
-from .lib import LimitReached, inc_limit_usage, dec_limit_usage
-from .models import LimitTemplates, LimitsPool
-from modoboa.lib import events
-from modoboa.lib.permissions import get_object_owner
-
-
-def check_limit(user, lname, count=1):
- """Check if a user has reached a defined limit
-
- We check if the user will not reach the given limit after this
- creation.
-
- :param user: a ``User`` object
- :param int count: the number of objects the user tries to create
- :raises: ``LimitReached``
- """
- try:
- if user.limitspool.will_be_reached(lname, count):
- raise LimitReached(user.limitspool.get_limit(lname))
- except LimitsPool.DoesNotExist:
- pass
-
-
-def move_pool_resource(owner, user):
- """Move resource from one pool to another
-
- When an account doesn't need a pool anymore, we move the
- associated resource to the pool of its owner.
- """
- try:
- pool = user.limitspool
- except LimitsPool.DoesNotExist:
- return
- if not owner.is_superuser:
- for ltpl in LimitTemplates().templates:
- l = user.limitspool.get_limit(ltpl[0])
- if l.maxvalue < 0:
- continue
- ol = owner.limitspool.get_limit(ltpl[0])
- ol.curvalue += l.curvalue
- ol.maxvalue += l.maxvalue
- ol.save()
-
- user.limitspool.delete()
-
-
-@events.observe('DomainCreated')
-def inc_nb_domains(user, domain):
- inc_limit_usage(user, 'domains_limit')
-
-
-@events.observe('DomainDeleted')
-def dec_nb_domains(domain, owner=None):
- if owner is None:
- owner = get_object_owner(domain)
- dec_limit_usage(owner, 'domains_limit')
- for domalias in domain.domainalias_set.all():
- dec_nb_domaliases(domalias)
- for mailbox in domain.mailbox_set.all():
- dec_nb_mailboxes(mailbox)
- for mbalias in domain.alias_set.all():
- dec_nb_mbaliases(mbalias)
-
-
-@events.observe('DomainAliasCreated')
-def inc_nb_domaliases(user, domalias):
- inc_limit_usage(user, 'domain_aliases_limit')
-
-
-@events.observe('DomainAliasDeleted')
-def dec_nb_domaliases(domainaliases):
- from modoboa.extensions.admin.models import DomainAlias
-
- if isinstance(domainaliases, DomainAlias):
- domainaliases = [domainaliases]
- for domainalias in domainaliases:
- owner = get_object_owner(domainalias)
- dec_limit_usage(owner, 'domain_aliases_limit')
-
-
-@events.observe('MailboxCreated')
-def inc_nb_mailboxes(user, mailbox):
- inc_limit_usage(user, 'mailboxes_limit')
-
-
-@events.observe('MailboxDeleted')
-def dec_nb_mailboxes(mailboxes):
- from modoboa.extensions.admin.models import Mailbox
-
- if isinstance(mailboxes, Mailbox):
- mailboxes = [mailboxes]
- for mailbox in mailboxes:
- owner = get_object_owner(mailbox)
- dec_limit_usage(owner, 'mailboxes_limit')
-
-
-@events.observe('MailboxAliasCreated')
-def inc_nb_mbaliases(user, mailboxalias):
- inc_limit_usage(user, 'mailbox_aliases_limit')
-
-
-@events.observe('MailboxAliasDeleted')
-def dec_nb_mbaliases(mailboxaliases):
- from modoboa.extensions.admin.models import Alias
-
- if isinstance(mailboxaliases, Alias):
- mailboxaliases = [mailboxaliases]
- for alias in mailboxaliases:
- owner = get_object_owner(alias)
- dec_limit_usage(owner, 'mailbox_aliases_limit')
-
-
-@events.observe('CanCreate')
-def can_create_new_object(user, objtype, count=1):
- check_limit(user, '%s_limit' % objtype, count)
-
-
-@events.observe("AccountCreated")
-def create_pool(user):
- owner = get_object_owner(user)
- if owner.group not in ['SuperAdmins', 'Resellers']:
- return
-
- if user.group == 'DomainAdmins':
- check_limit(owner, 'domain_admins_limit')
- inc_limit_usage(owner, 'domain_admins_limit')
-
- if user.group in ['DomainAdmins', 'Resellers']:
- p, created = LimitsPool.objects.get_or_create(user=user)
- p.create_limits(owner)
-
-
-@events.observe("UserCanSetRole")
-def user_can_set_role(user, role, account=None):
- """Check if the user can still set this role.
-
- The only interesting case concerns resellers defining new domain
- administrators. We want to check if they are allowed to do this
- operation before any modification is made to :keyword:`account`.
-
- :param ``User`` user: connected user
- :param ``User`` account: account modified (None on creation)
- :param str newrole: role to check
- """
- if role == 'DomainAdmins':
- lname = 'domain_admins_limit'
- else:
- return [True]
- if user.is_superuser or not user.limitspool.will_be_reached(lname):
- return [True]
- if account is not None and account.group == role:
- return [True]
- return [False]
-
-
-@events.observe("AccountModified")
-def on_account_modified(old, new):
- """Update limits when roles are updated"""
- owner = get_object_owner(old)
- if owner.group not in ["SuperAdmins", "Resellers"]:
- # Domain admins can't change the role so nothing to check.
- return
-
- if new.group != "SuperAdmins":
- # Check if account needs a pool (case: a superadmin is
- # downgraded)
- try:
- pool = new.limitspool
- except LimitsPool.DoesNotExist:
- p = LimitsPool(user=new)
- p.save()
- p.create_limits(owner)
-
- if new.group not in ["DomainAdmins", "Resellers"]:
- move_pool_resource(owner, new)
-
- if old.oldgroup == "DomainAdmins":
- if new.group != "DomainAdmins":
- dec_limit_usage(owner, 'domain_admins_limit')
- return
-
- if new.group == "DomainAdmins":
- check_limit(owner, 'domain_admins_limit')
- inc_limit_usage(owner, 'domain_admins_limit')
-
-
-@events.observe("AccountDeleted")
-def on_account_deleted(account, byuser, **kwargs):
- owner = get_object_owner(account)
- if owner.group not in ["SuperAdmins", "Resellers"]:
- return
-
- move_pool_resource(owner, account)
-
- if account.group == "DomainAdmins":
- dec_limit_usage(owner, 'domain_admins_limit')
-
-
-@events.observe('DomainOwnershipRemoved')
-def domain_ownership_removed(reseller, domain):
- """DomainOwnershipRemoved listener.
-
- The access :keyword:`reseller` had to :keyword:`domain` has been
- removed by a super adminstrator. We must decrement all limit
- usages.
-
- :param ``User`` reseller: reseller that created :keyword:`domain`
- :param ``Domain`` domain: domain
- """
- dec_nb_domains(domain, reseller)
- for dadmin in domain.admins:
- if reseller.is_owner(dadmin):
- dec_limit_usage(reseller, 'domain_admins_limit')
diff --git a/modoboa/extensions/limits/fixtures/demo.json b/modoboa/extensions/limits/fixtures/demo.json
deleted file mode 100644
index 52a9bc1a1..000000000
--- a/modoboa/extensions/limits/fixtures/demo.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"pk": 1, "model": "limits.limitspool", "fields": {"user": 2}}, {"pk": 1, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domain_admins_limit", "pool": 1, "maxvalue": -2}}, {"pk": 2, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domains_limit", "pool": 1, "maxvalue": -2}}, {"pk": 3, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domain_aliases_limit", "pool": 1, "maxvalue": -2}}, {"pk": 4, "model": "limits.limit", "fields": {"curvalue": 0, "name": "mailboxes_limit", "pool": 1, "maxvalue": 5}}, {"pk": 5, "model": "limits.limit", "fields": {"curvalue": 0, "name": "mailbox_aliases_limit", "pool": 1, "maxvalue": 5}},{"pk": 3, "model": "auth.group", "fields": {"name": "Resellers", "permissions": [["add_user", "core", "user"], ["change_user", "core", "user"], ["delete_user", "core", "user"], ["view_domains", "admin", "domain"], ["add_mailbox", "admin", "mailbox"], ["change_mailbox", "admin", "mailbox"], ["delete_mailbox", "admin", "mailbox"], ["add_alias", "admin", "alias"], ["change_alias", "admin", "alias"], ["delete_alias", "admin", "alias"], ["view_mailboxes", "admin", "mailbox"], ["view_aliases", "admin", "alias"], ["view_domaliases", "admin", "domainalias"], ["add_domainalias", "admin", "domainalias"], ["change_domainalias", "admin", "domainalias"], ["delete_domainalias", "admin", "domainalias"], ["view_domains", "admin", "domain"], ["add_domain", "admin", "domain"], ["change_domain", "admin", "domain"], ["delete_domain", "admin", "domain"]]}}]
\ No newline at end of file
diff --git a/modoboa/extensions/limits/forms.py b/modoboa/extensions/limits/forms.py
deleted file mode 100644
index b96d10ef3..000000000
--- a/modoboa/extensions/limits/forms.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# coding: utf-8
-
-"""Custom forms."""
-
-from django import forms
-from django.utils.translation import ugettext as _
-
-from .lib import BadLimitValue, UnsufficientResource
-from .models import LimitTemplates
-from modoboa.lib import parameters
-
-
-class ResourcePoolForm(forms.Form):
-
- def __init__(self, *args, **kwargs):
- self.account = None
- if "instance" in kwargs:
- self.account = kwargs["instance"]
- del kwargs["instance"]
- super(ResourcePoolForm, self).__init__(*args, **kwargs)
- for tpl in LimitTemplates().templates:
- if len(tpl) > 3:
- if self.account is not None and self.account.group != tpl[3]:
- continue
- self.fields[tpl[0]] = forms.IntegerField(
- label=tpl[1], help_text=tpl[2]
- )
- if hasattr(self, "account"):
- self.load_from_user(self.account)
-
- def check_limit_value(self, lname):
- if self.cleaned_data[lname] < -1:
- raise forms.ValidationError(_("Invalid limit"))
- return self.cleaned_data[lname]
-
- def clean(self):
- cleaned_data = super(ResourcePoolForm, self).clean()
- for lname in self.fields.keys():
- if lname not in self._errors and cleaned_data[lname] < -1:
- self.add_error(lname, _("Invalid limit"))
- return cleaned_data
-
- def load_from_user(self, user):
- for lname in self.fields.keys():
- self.fields[lname].initial = user.limitspool.getmaxvalue(lname)
- # The following lines will become useless in a near
- # future.
- if self.fields[lname].initial == -2:
- self.fields[lname].initial = parameters.get_admin(
- "DEFLT_%s" %
- lname.upper())
-
- def allocate_from_pool(self, limit, pool):
- """Allocate resource using an existing pool.
-
- When a reseller creates a domain administrator, he generally
- assigns him resource to create new objetcs. As a reseller may
- also be limited, the resource he gives is taken from its own
- pool.
- """
- ol = pool.get_limit(limit.name)
- if ol.maxvalue == -2:
- raise BadLimitValue(_("Your resources are not initialized yet"))
- newvalue = self.cleaned_data[limit.name]
- if newvalue == -1 and ol.maxvalue != -1:
- raise BadLimitValue(
- _("You're not allowed to define unlimited values")
- )
-
- if limit.maxvalue > -1:
- newvalue -= limit.maxvalue
- if newvalue == 0:
- return
- remain = ol.maxvalue - ol.curvalue
- if newvalue > remain:
- raise UnsufficientResource(ol)
- ol.maxvalue -= newvalue
- ol.save()
-
- def save(self):
- from modoboa.lib.permissions import get_object_owner
-
- owner = get_object_owner(self.account)
- for ltpl in LimitTemplates().templates:
- if ltpl[0] not in self.cleaned_data:
- continue
- l = self.account.limitspool.limit_set.get(name=ltpl[0])
- if not owner.is_superuser:
- self.allocate_from_pool(l, owner.limitspool)
- l.maxvalue = self.cleaned_data[ltpl[0]]
- l.save()
diff --git a/modoboa/extensions/limits/general_callbacks.py b/modoboa/extensions/limits/general_callbacks.py
deleted file mode 100644
index 3f207eebc..000000000
--- a/modoboa/extensions/limits/general_callbacks.py
+++ /dev/null
@@ -1,123 +0,0 @@
-"""General event callbacks."""
-
-from django.utils.translation import ugettext as _
-
-from modoboa.core import PERMISSIONS as CORE_PERMS
-from modoboa.extensions.admin.modo_extension import PERMISSIONS as ADMIN_PERMS
-from modoboa.extensions.limits.forms import ResourcePoolForm
-from modoboa.extensions.limits.models import LimitTemplates
-from modoboa.lib import events
-
-
-PERMISSIONS = {
- "Resellers": (
- CORE_PERMS.get("DomainAdmins") +
- ADMIN_PERMS.get("DomainAdmins") +
- [["admin", "domain", "view_domains"],
- ["admin", "domain", "add_domain"],
- ["admin", "domain", "change_domain"],
- ["admin", "domain", "delete_domain"]]
- )
-}
-
-
-@events.observe("GetExtraRoles")
-def get_extra_roles(user):
- if user.is_superuser:
- return [("Resellers", _("Reseller")), ]
- return []
-
-
-@events.observe("GetExtraRolePermissions")
-def extra_permissions(rolename):
- """Return extra permissions for Resellers."""
- return PERMISSIONS.get(rolename, [])
-
-
-@events.observe("ExtraAdminContent")
-def display_pool_usage(user, target, currentpage):
- from django.template.loader import render_to_string
-
- if target != "leftcol" or user.is_superuser:
- return []
- if currentpage == "identities":
- names = ["mailboxes_limit", "mailbox_aliases_limit"]
- if user.has_perm("admin.add_domain"):
- names += ["domain_admins_limit"]
- else:
- names = [
- tpl[0] for tpl in LimitTemplates().templates
- if tpl[0] not in ["domain_admins_limit", "mailboxes_limit",
- "mailbox_aliases_limit"]
- and (len(tpl) == 3 or tpl[3] == user.group)
- ]
-
- limits = user.limitspool.limit_set.filter(name__in=names, maxvalue__gt=0)
- if len(limits) == 0:
- return []
- return [render_to_string("limits/poolusage.html", dict(limits=limits))]
-
-
-@events.observe("ExtraAccountForm")
-def extra_account_form(user, account=None):
- if user.group not in ["SuperAdmins", "Resellers"]:
- return []
- if account is not None and \
- account.group not in ["Resellers", "DomainAdmins"]:
- return []
-
- return [
- dict(
- id="resources", title=_("Resources"), cls=ResourcePoolForm
- )
- ]
-
-
-@events.observe("CheckExtraAccountForm")
-def check_form_access(account, form):
- if form["id"] != "resources":
- return [True]
- if not account.belongs_to_group("Resellers") and \
- not account.belongs_to_group("DomainAdmins"):
- return [False]
- return [True]
-
-
-@events.observe("FillAccountInstances")
-def fill_account_instances(user, account, instances):
- if not user.is_superuser and not user.belongs_to_group("Resellers"):
- return
- if not account.belongs_to_group("Resellers") and \
- not account.belongs_to_group("DomainAdmins"):
- return
- instances["resources"] = account
-
-
-@events.observe("GetStaticContent")
-def get_static_content(caller, st_type, user):
- if caller not in ['domains', 'identities']:
- return []
- if user.group == "SimpleUsers":
- return []
- if st_type == "css":
- return ["""
-"""]
- return ["""
-
-"""]
diff --git a/modoboa/extensions/limits/lib.py b/modoboa/extensions/limits/lib.py
deleted file mode 100644
index c0135a234..000000000
--- a/modoboa/extensions/limits/lib.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# coding: utf-8
-"""
-:mod:`lib` --- public functions
--------------------------------
-
-"""
-from django.utils.translation import ugettext as _
-
-from modoboa.extensions.limits.models import LimitsPool
-from modoboa.lib.exceptions import ModoboaException
-
-
-class LimitReached(ModoboaException):
- http_code = 403
-
- def __init__(self, limit):
- self.limit = limit
-
- def __str__(self):
- return _("%s: limit reached") % self.limit.label
-
-
-class UnsufficientResource(ModoboaException):
- http_code = 424
-
- def __init__(self, limit):
- self.limit = limit
-
- def __str__(self):
- return _("Not enough resources")
-
-
-class BadLimitValue(ModoboaException):
- http_code = 400
-
-
-def inc_limit_usage(user, lname):
- """Increase a given limit usage.
-
- """
- try:
- user.limitspool.inc_curvalue(lname)
- except LimitsPool.DoesNotExist:
- pass
-
-
-def dec_limit_usage(user, lname):
- if user is None:
- return
- try:
- user.limitspool.dec_curvalue(lname)
- except LimitsPool.DoesNotExist:
- pass
diff --git a/modoboa/extensions/limits/migrations/0001_initial.py b/modoboa/extensions/limits/migrations/0001_initial.py
deleted file mode 100644
index 82ed516e3..000000000
--- a/modoboa/extensions/limits/migrations/0001_initial.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-from django.conf import settings
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Limit',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=255)),
- ('curvalue', models.IntegerField(default=0)),
- ('maxvalue', models.IntegerField(default=-2)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='LimitsPool',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.AddField(
- model_name='limit',
- name='pool',
- field=models.ForeignKey(to='limits.LimitsPool'),
- preserve_default=True,
- ),
- migrations.AlterUniqueTogether(
- name='limit',
- unique_together=set([('name', 'pool')]),
- ),
- ]
diff --git a/modoboa/extensions/limits/migrations/__init__.py b/modoboa/extensions/limits/migrations/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/limits/models.py b/modoboa/extensions/limits/models.py
deleted file mode 100644
index 60ced9325..000000000
--- a/modoboa/extensions/limits/models.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# coding: utf-8
-
-"""Models for the limits extensions."""
-
-from django.conf import settings
-from django.db import models
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.lib import parameters, events
-from modoboa.lib.singleton import Singleton
-
-
-class LimitTemplates(Singleton):
-
- def __init__(self):
- self.__templates = [
- ("domain_admins_limit", ugettext_lazy("Domain admins"),
- ugettext_lazy("Maximum number of domain administrators this user "
- "can create"),
- 'Resellers'),
- ("domains_limit", ugettext_lazy("Domains"),
- ugettext_lazy("Maximum number of domains this user can create"),
- 'Resellers'),
- ("domain_aliases_limit", ugettext_lazy("Domain aliases"),
- ugettext_lazy(
- "Maximum number of domain aliases this user can create"),
- 'Resellers'),
- ("mailboxes_limit", ugettext_lazy("Mailboxes"),
- ugettext_lazy("Maximum number of mailboxes this user can create")),
- ("mailbox_aliases_limit", ugettext_lazy("Mailbox aliases"),
- ugettext_lazy("Maximum number of mailbox aliases this user "
- "can create"))
- ]
-
- @property
- def templates(self):
- return self.__templates + \
- events.raiseQueryEvent('GetExtraLimitTemplates')
-
-
-class LimitsPool(models.Model):
- user = models.OneToOneField(settings.AUTH_USER_MODEL)
-
- def create_limits(self, creator):
- """Create limits for this pool.
-
- All limits defined into ``LimitTemplates`` will be created. If
- the creator is a super administrator, the default maximum values
- will be used.
-
- :param ``User`` creator: user creating this pool
- """
- for ltpl in LimitTemplates().templates:
- try:
- Limit.objects.get(name=ltpl[0], pool=self)
- except Limit.DoesNotExist:
- maxvalue = (
- int(parameters.get_admin("DEFLT_%s" % ltpl[0].upper()))
- if creator.is_superuser else 0
- )
- Limit.objects.create(
- name=ltpl[0], pool=self, maxvalue=maxvalue
- )
-
- def getcurvalue(self, lname):
- l = self.limit_set.get(name=lname)
- return l.curvalue
-
- def getmaxvalue(self, lname):
- l = self.limit_set.get(name=lname)
- return l.maxvalue
-
- def set_maxvalue(self, lname, value):
- l = self.limit_set.get(name=lname)
- l.maxvalue = value
- l.save()
-
- def inc_curvalue(self, lname, nb=1):
- l = self.limit_set.get(name=lname)
- l.curvalue += nb
- l.save()
-
- def dec_curvalue(self, lname, nb=1):
- l = self.limit_set.get(name=lname)
- if not l.curvalue:
- return
- l.curvalue -= nb
- l.save()
-
- def dec_limit(self, lname, nb=1):
- l = self.limit_set.get(name=lname)
- l.curvalue -= nb
- if l.maxvalue > -1:
- l.maxvalue -= nb
- l.save()
-
- def inc_limit(self, lname, nb=1):
- l = self.limit_set.get(name=lname)
- l.curvalue += nb
- if l.maxvalue > -1:
- l.maxvalue += nb
- l.save()
-
- def will_be_reached(self, lname, nb=1):
- l = self.limit_set.get(name=lname)
- if l.maxvalue <= -1:
- return False
- if l.curvalue + nb > l.maxvalue:
- return True
- return False
-
- def get_limit(self, lname):
- try:
- return self.limit_set.get(name=lname)
- except Limit.DoesNotExist:
- return None
-
-
-class Limit(models.Model):
- name = models.CharField(max_length=255)
- curvalue = models.IntegerField(default=0)
- maxvalue = models.IntegerField(default=-2)
- pool = models.ForeignKey(LimitsPool)
-
- class Meta:
- unique_together = (("name", "pool"),)
-
- @property
- def usage(self):
- if self.maxvalue < 0:
- return -1
- if self.maxvalue == 0:
- return 0
- return int(float(self.curvalue) / self.maxvalue * 100)
-
- @property
- def label(self):
- for l in LimitTemplates().templates:
- if l[0] == self.name:
- return l[1]
- return ""
-
- def __str__(self):
- if self.maxvalue == -2:
- return _("undefined")
- if self.maxvalue == -1:
- return _("unlimited")
- return "%d%%" % self.usage
diff --git a/modoboa/extensions/limits/modo_extension.py b/modoboa/extensions/limits/modo_extension.py
deleted file mode 100644
index 45a8659a6..000000000
--- a/modoboa/extensions/limits/modo_extension.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# coding: utf-8
-
-"""
-The *limits* extension
-----------------------
-"""
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.core.models import User
-from modoboa.lib import events, parameters
-from .models import LimitTemplates, LimitsPool, Limit
-
-
-EVENTS = [
- 'GetExtraLimitTemplates'
-]
-
-
-class Limits(ModoExtension):
- name = "limits"
- label = "Limits"
- version = "1.0"
- description = ugettext_lazy(
- "Per administrator resources to limit the number of objects "
- "they can create"
- )
-
- def load(self):
- from modoboa.extensions.limits.app_settings import ParametersForm
- from modoboa.extensions.limits import controls
-
- parameters.register(ParametersForm, ugettext_lazy("Limits"))
- events.declare(EVENTS)
- from modoboa.extensions.limits import general_callbacks
-
- def load_initial_data(self):
- """Create pools for existing accounts."""
- for user in User.objects.filter(groups__name="DomainAdmins"):
- pool, created = LimitsPool.objects.get_or_create(user=user)
- for tpl in LimitTemplates().templates:
- Limit.objects.get_or_create(name=tpl[0], pool=pool, maxvalue=0)
-
-exts_pool.register_extension(Limits)
diff --git a/modoboa/extensions/limits/templates/limits/poolusage.html b/modoboa/extensions/limits/templates/limits/poolusage.html
deleted file mode 100644
index 1665b6d31..000000000
--- a/modoboa/extensions/limits/templates/limits/poolusage.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% load i18n lib_tags %}
-
diff --git a/modoboa/extensions/limits/tests.py b/modoboa/extensions/limits/tests.py
deleted file mode 100644
index 69b737714..000000000
--- a/modoboa/extensions/limits/tests.py
+++ /dev/null
@@ -1,394 +0,0 @@
-"""Test cases for the limits extension."""
-
-from django.core.urlresolvers import reverse
-
-from modoboa.core.factories import UserFactory
-from modoboa.core.models import User
-from modoboa.extensions.admin.factories import (
- populate_database
-)
-from modoboa.extensions.admin.models import Alias, Domain
-from modoboa.extensions.limits.models import LimitTemplates
-from modoboa.lib import parameters
-from modoboa.lib.tests import ModoTestCase
-
-
-class PermissionsTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- super(PermissionsTestCase, self).setUp()
- populate_database()
-
- def test_domainadmin_deletes_reseller(self):
- """Check if a domain admin can delete a reseller.
-
- Expected result: no.
- """
- values = dict(
- username="reseller@test.com", first_name="Reseller", last_name="",
- password1="toto", password2="toto", role="Resellers",
- is_active=True, email="reseller@test.com", stepid='step2'
- )
- self.ajax_post(reverse("admin:account_add"), values)
- account = User.objects.get(username="reseller@test.com")
- self.clt.logout()
- self.clt.login(username="admin@test.com", password="toto")
- resp = self.ajax_post(
- reverse("admin:account_delete", args=[account.id]),
- {}, status=403
- )
- self.assertEqual(resp, "Permission denied")
-
-
-class ResourceTestCase(ModoTestCase):
- fixtures = ["initial_users.json"]
-
- def setUp(self):
- """Custom setUp method.
-
- The 'limits' is manually loaded to ensure extra parameters
- provided by 'postfix_relay_domains' are properly received.
- """
- super(ResourceTestCase, self).setUp()
- for tpl in LimitTemplates().templates:
- parameters.save_admin('DEFLT_%s' % tpl[0].upper(), 2, app='limits')
- populate_database()
-
- def _create_account(self, username, role='SimpleUsers', status=200):
- values = dict(
- username=username, first_name="Tester", last_name="Toto",
- password1="toto", password2="toto", role=role,
- quota_act=True,
- is_active=True, email=username, stepid='step2',
- )
- return self.ajax_post(
- reverse("admin:account_add"), values, status
- )
-
- def _create_alias(self, email, rcpt='user@test.com', status=200):
- values = dict(
- email=email, recipients=rcpt, enabled=True
- )
- return self.ajax_post(
- reverse("admin:alias_add"), values, status
- )
-
- def _create_domain(self, name, status=200, withtpl=False):
- values = {
- "name": name, "quota": 100, "create_dom_admin": "no",
- "create_aliases": "no", "stepid": 'step2'
- }
- if withtpl:
- values['create_dom_admin'] = 'yes'
- values['dom_admin_username'] = 'admin'
- values['create_aliases'] = 'yes'
- return self.ajax_post(
- reverse("admin:domain_add"), values, status
- )
-
- def _domain_alias_operation(self, optype, domain, name, status=200):
- dom = Domain.objects.get(name=domain)
- values = {
- 'name': dom.name, 'quota': dom.quota, 'enabled': dom.enabled,
- }
- aliases = [alias.name for alias in dom.domainalias_set.all()]
- if optype == 'add':
- aliases.append(name)
- else:
- aliases.remove(name)
- for cpt, alias in enumerate(aliases):
- fname = 'aliases' if not cpt else 'aliases_%d' % cpt
- values[fname] = alias
- self.ajax_post(
- reverse("admin:domain_change", args=[dom.id]),
- values, status
- )
-
- def _check_limit(self, name, curvalue, maxvalue):
- l = self.user.limitspool.get_limit('%s_limit' % name)
- self.assertEqual(l.curvalue, curvalue)
- self.assertEqual(l.maxvalue, maxvalue)
-
-
-class DomainAdminTestCase(ResourceTestCase):
-
- def setUp(self):
- super(DomainAdminTestCase, self).setUp()
- self.user = User.objects.get(username='admin@test.com')
- self.user.limitspool.set_maxvalue('mailboxes_limit', 2)
- self.user.limitspool.set_maxvalue('mailbox_aliases_limit', 2)
- self.clt.logout()
- self.clt.login(username='admin@test.com', password='toto')
-
- def test_mailboxes_limit(self):
- self._create_account('tester1@test.com')
- self._check_limit('mailboxes', 1, 2)
- self._create_account('tester2@test.com')
- self._check_limit('mailboxes', 2, 2)
- resp = self._create_account('tester3@test.com', status=403)
- self._check_limit('mailboxes', 2, 2)
- self.ajax_post(
- reverse('admin:account_delete',
- args=[User.objects.get(username='tester2@test.com').id]),
- {}
- )
- self._check_limit('mailboxes', 1, 2)
-
- def test_aliases_limit(self):
- self._create_alias('alias1@test.com')
- self._check_limit('mailbox_aliases', 1, 2)
- self._create_alias('alias2@test.com')
- self._check_limit('mailbox_aliases', 2, 2)
- resp = self._create_alias('alias3@test.com', status=403)
- self._check_limit('mailbox_aliases', 2, 2)
- self.ajax_post(
- reverse('admin:alias_delete') + '?selection=%d'
- % Alias.objects.get(address='alias2', domain__name='test.com').id,
- {}
- )
- self._check_limit('mailbox_aliases', 1, 2)
-
- def test_aliases_limit_through_account_form(self):
- user = User.objects.get(username='user@test.com')
- values = dict(
- username=user.username, role=user.group,
- is_active=user.is_active, email=user.email, quota_act=True,
- aliases="alias1@test.com", aliases_1="alias2@test.com"
- )
- self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values
- )
- Alias.objects.get(address='alias1', domain__name='test.com')
- self._check_limit('mailbox_aliases', 2, 2)
-
-
-class ResellerTestCase(ResourceTestCase):
-
- def setUp(self):
- super(ResellerTestCase, self).setUp()
- self.user = UserFactory.create(
- username='reseller', groups=('Resellers',)
- )
- self.clt.logout()
- self.clt.login(username='reseller', password='toto')
-
- def test_domains_limit(self):
- self._create_domain('domain1.tld')
- self._check_limit('domains', 1, 2)
- self._create_domain('domain2.tld')
- self._check_limit('domains', 2, 2)
- resp = self._create_domain('domain3.tld', 403)
- self._check_limit('domains', 2, 2)
- self.ajax_post(
- reverse('admin:domain_delete',
- args=[Domain.objects.get(name='domain2.tld').id]),
- {}
- )
- self._check_limit('domains', 1, 2)
-
- def test_domain_aliases_limit(self):
- self._create_domain('pouet.com')
- self._domain_alias_operation('add', 'pouet.com', 'domain_alias1.tld')
- self._check_limit('domain_aliases', 1, 2)
- self._domain_alias_operation('add', 'pouet.com', 'domain_alias2.tld')
- self._check_limit('domain_aliases', 2, 2)
- resp = self._domain_alias_operation(
- 'add', 'pouet.com', 'domain_alias3.tld', 403
- )
- self._check_limit('domain_aliases', 2, 2)
- self._domain_alias_operation('delete', 'pouet.com', 'domain_alias2.tld')
- self._check_limit('domain_aliases', 1, 2)
-
- def test_domain_admins_limit(self):
- self._create_domain('domain.tld')
- self._create_account('admin1@domain.tld', role='DomainAdmins')
- self._check_limit('domain_admins', 1, 2)
- self._create_account('admin2@domain.tld', role='DomainAdmins')
- self._check_limit('domain_admins', 2, 2)
- resp = self._create_account(
- 'admin3@domain.tld',
- role='DomainAdmins',
- status=400)
- self.assertEqual(
- resp['form_errors']['role'][0],
- 'Select a valid choice. DomainAdmins is not one of the available '
- 'choices.'
- )
- self._check_limit('domain_admins', 2, 2)
-
- self.user.limitspool.set_maxvalue('mailboxes_limit', 3)
- self._create_account('user1@domain.tld')
- user = User.objects.get(username='user1@domain.tld')
- values = {
- 'username': user.username, 'role': 'DomainAdmins',
- 'quota_act': True, 'is_active': user.is_active,
- 'email': user.email
- }
- resp = self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values, status=400
- )
- self.assertEqual(
- resp['form_errors']['role'][0],
- 'Select a valid choice. DomainAdmins is not one of the available '
- 'choices.'
- )
- self._check_limit('domain_admins', 2, 2)
-
- def test_domain_admin_resource_are_empty(self):
- self._create_domain('domain.tld')
- self._create_account('admin1@domain.tld', role='DomainAdmins')
- domadmin = User.objects.get(username='admin1@domain.tld')
- for l in ['mailboxes', 'mailbox_aliases']:
- self.assertEqual(
- domadmin.limitspool.get_limit('%s_limit' % l).maxvalue, 0
- )
-
- def test_domain_admins_limit_from_domain_tpl(self):
- self.user.limitspool.set_maxvalue('domains_limit', 3)
- self._create_domain('domain1.tld', withtpl=True)
- self._create_domain('domain2.tld', withtpl=True)
- self._check_limit('domain_admins', 2, 2)
- self._check_limit('domains', 2, 3)
- resp = self._create_domain('domain3.tld', status=200, withtpl=True)
- self._check_limit('domain_admins', 2, 2)
- self._check_limit('domains', 3, 3)
-
- def test_reseller_deletes_domain(self):
- """Check if all resources are restored after the deletion.
- """
- self._create_domain('domain.tld', withtpl=True)
- dom = Domain.objects.get(name="domain.tld")
- self.ajax_post(
- reverse("admin:domain_delete", args=[dom.id]),
- {}
- )
- self._check_limit('domains', 0, 2)
- self._check_limit('domain_admins', 1, 2)
- self._check_limit('mailboxes', 0, 2)
- self._check_limit('mailbox_aliases', 0, 2)
-
- def test_sadmin_removes_ownership(self):
- self._create_domain('domain.tld', withtpl=True)
- dom = Domain.objects.get(name="domain.tld")
- self.clt.logout()
- self.clt.login(username='admin', password='password')
- self.ajax_get(
- "{0}?domid={1}&daid={2}".format(
- reverse('admin:permission_remove'), dom.id, self.user.id
- ), {}
- )
- self._check_limit('domains', 0, 2)
- self._check_limit('domain_admins', 0, 2)
- self._check_limit('mailboxes', 0, 2)
- self._check_limit('mailbox_aliases', 0, 2)
-
- def test_allocate_from_pool(self):
- self._create_domain('domain.tld')
- self._create_account('admin1@domain.tld', role='DomainAdmins')
- user = User.objects.get(username='admin1@domain.tld')
-
- # Give 1 mailbox and 2 aliases to the admin -> should work
- values = {
- 'username': user.username, 'role': user.group, 'quota_act': True,
- 'is_active': user.is_active, 'email': user.email,
- 'mailboxes_limit': 1, 'mailbox_aliases_limit': 2
- }
- self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values
- )
- self._check_limit('mailboxes', 1, 1)
- self._check_limit('mailbox_aliases', 0, 0)
-
- # Delete the admin -> resources should go back to the
- # reseller's pool
- self.ajax_post(
- reverse("admin:account_delete", args=[user.id]),
- {}
- )
- self._check_limit('mailboxes', 0, 2)
- self._check_limit('mailbox_aliases', 0, 2)
-
- def test_restore_resources(self):
- self._create_domain('domain.tld')
- dom = Domain.objects.get(name='domain.tld')
- self._create_account('admin1@domain.tld', role='DomainAdmins')
- user = User.objects.get(username='admin1@domain.tld')
- values = {
- 'username': user.username, 'role': user.group, 'quota_act': True,
- 'is_active': user.is_active, 'email': user.email,
- 'mailboxes_limit': 1, 'mailbox_aliases_limit': 2
- }
- self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values
- )
- dom.add_admin(user)
- self.clt.logout()
- self.clt.login(username='admin1@domain.tld', password='toto')
- self._create_account('user1@domain.tld')
- self._create_alias('alias1@domain.tld', 'user1@domain.tld')
- self._create_alias('alias2@domain.tld', 'user1@domain.tld')
- self.clt.logout()
- self.clt.login(username='reseller', password='toto')
- # Delete the admin -> resources should go back to the
- # reseller's pool
- self.ajax_post(
- reverse("admin:account_delete", args=[user.id]),
- {}
- )
- self._check_limit('mailboxes', 1, 2)
- self._check_limit('mailbox_aliases', 2, 2)
-
- def test_change_role(self):
- self._create_domain('domain.tld')
- self._create_account('admin1@domain.tld', role='DomainAdmins')
- user = User.objects.get(username='admin1@domain.tld')
-
- # Give 1 mailbox and 2 aliases to the admin -> should work
- values = {
- 'username': user.username, 'role': user.group, 'quota_act': True,
- 'is_active': user.is_active, 'email': user.email,
- 'mailboxes_limit': 1, 'mailbox_aliases_limit': 2
- }
- self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values
- )
- self._check_limit('mailboxes', 1, 1)
- self._check_limit('mailbox_aliases', 0, 0)
-
- # Change admin role to SimpleUser -> resources should go back
- # to the reseller.
- values = {
- 'username': user.username, 'role': 'SimpleUsers', 'quota_act': True,
- 'is_active': user.is_active, 'email': user.email,
- }
- self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values
- )
- self._check_limit('mailboxes', 1, 2)
- self._check_limit('mailbox_aliases', 0, 2)
-
- def test_allocate_too_much(self):
- self._create_domain('domain.tld')
- self._create_account('admin1@domain.tld', role='DomainAdmins')
- user = User.objects.get(username='admin1@domain.tld')
-
- # Give 2 mailboxes and 3 aliases to the admin -> should fail.
- values = {
- 'username': user.username, 'role': user.group, 'quota_act': True,
- 'is_active': user.is_active, 'email': user.email,
- 'mailboxes_limit': 2, 'mailbox_aliases_limit': 3
- }
- resp = self.ajax_post(
- reverse("admin:account_change", args=[user.id]),
- values, 424
- )
- self.assertEqual(resp, 'Not enough resources')
- self._check_limit('mailboxes', 1, 2)
- self._check_limit('mailbox_aliases', 0, 2)
diff --git a/modoboa/extensions/limits/urls.py b/modoboa/extensions/limits/urls.py
deleted file mode 100644
index 9adc5e04a..000000000
--- a/modoboa/extensions/limits/urls.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from django.conf.urls import patterns
-
-urlpatterns = patterns(
- 'modoboa.extensions.limits.views',
-
-)
diff --git a/modoboa/extensions/limits/views.py b/modoboa/extensions/limits/views.py
deleted file mode 100644
index 57d631c3f..000000000
--- a/modoboa/extensions/limits/views.py
+++ /dev/null
@@ -1 +0,0 @@
-# coding: utf-8
diff --git a/modoboa/extensions/stats/__init__.py b/modoboa/extensions/stats/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/stats/app_settings.py b/modoboa/extensions/stats/app_settings.py
deleted file mode 100644
index 9c48d156e..000000000
--- a/modoboa/extensions/stats/app_settings.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# coding: utf-8
-from django.utils.translation import ugettext_lazy
-from django import forms
-from modoboa.lib.parameters import AdminParametersForm
-from modoboa.lib.form_utils import SeparatorField
-
-
-class ParametersForm(AdminParametersForm):
- app = "stats"
-
- general_sep = SeparatorField(label=ugettext_lazy("General"))
-
- logfile = forms.CharField(
- label=ugettext_lazy("Path to the log file"),
- initial="/var/log/mail.log",
- help_text=ugettext_lazy("Path to log file used to collect statistics"),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- rrd_rootdir = forms.CharField(
- label=ugettext_lazy("Directory to store RRD files"),
- initial="/tmp/modoboa",
- help_text=ugettext_lazy("Path to directory where RRD files are stored"),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
diff --git a/modoboa/extensions/stats/general_callbacks.py b/modoboa/extensions/stats/general_callbacks.py
deleted file mode 100644
index e6112736d..000000000
--- a/modoboa/extensions/stats/general_callbacks.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext as _
-from modoboa.lib import events
-
-
-@events.observe("UserMenuDisplay")
-def menu(target, user):
- if target != "top_menu" or user.group == "SimpleUsers":
- return []
- return [
- {"name": "stats",
- "label": _("Statistics"),
- "url": reverse('stats:fullindex')}
- ]
-
-
-@events.observe("GetGraphSets")
-def get_default_graphic_sets():
- from modoboa.extensions.stats.graphics import MailTraffic
-
- gset = MailTraffic()
- return {gset.html_id: gset}
diff --git a/modoboa/extensions/stats/graphics.py b/modoboa/extensions/stats/graphics.py
deleted file mode 100644
index 80ca0af88..000000000
--- a/modoboa/extensions/stats/graphics.py
+++ /dev/null
@@ -1,161 +0,0 @@
-import os
-import inspect
-from lxml import etree
-from django.utils.translation import ugettext_lazy
-from modoboa.lib import parameters
-from modoboa.lib.sysutils import exec_cmd
-
-
-class Curve(object):
-
- """Graphic curve.
-
- Simple way to represent a graphic curve.
- """
-
- def __init__(self, dsname, color, legend, cfunc="AVERAGE"):
- """Constructor.
- """
- self.dsname = dsname
- self.color = color
- self.legend = legend.encode("utf-8")
- self.cfunc = cfunc
-
- def to_rrd_command_args(self, rrdfile):
- """Convert this curve to the approriate RRDtool command.
-
- :param str rrdfile: RRD file name
- :return: a list
- """
- rrdfile = os.path.join(
- parameters.get_admin("RRD_ROOTDIR"), "%s.rrd" % rrdfile
- )
- return [
- 'DEF:%s=%s:%s:%s' %
- (self.dsname, rrdfile, self.dsname, self.cfunc),
- 'CDEF:%(ds)spm=%(ds)s,60,*' % {"ds": self.dsname},
- 'XPORT:%spm:"%s"' % (self.dsname, self.legend.decode("utf-8"))
- ]
-
-
-class Graphic(object):
-
- """Graphic.
-
- """
-
- def __init__(self):
- """Constructor.
- """
- self._curves = []
- try:
- order = getattr(self, "order")
- except AttributeError:
- for member in inspect.getmembers(self):
- if isinstance(member[1], Curve):
- self._curves += [member[1]]
- else:
- for name in order:
- try:
- curve = getattr(self, name)
- except AttributeError:
- continue
- if not isinstance(curve, Curve):
- continue
- self._curves += [curve]
-
- @property
- def display_name(self):
- return self.__class__.__name__.lower()
-
- def export(self, rrdfile, start, end):
- """
- """
- result = []
- cmdargs = []
- for curve in self._curves:
- result += [{
- "name": curve.legend, "color": curve.color, "data": []
- }]
- cmdargs += curve.to_rrd_command_args(rrdfile)
- cmd = "rrdtool xport --start %s --end %s " % (str(start), str(end))
- cmd += " ".join(cmdargs)
- if isinstance(cmd, unicode):
- cmd = cmd.encode("utf-8")
- code, output = exec_cmd(cmd)
- if code:
- return []
- tree = etree.fromstring(output)
- for row in tree.xpath('/xport/data/row'):
- timestamp = int(row.find('t').text)
- for vindex, value in enumerate(row.findall('v')):
- if value.text == 'NaN':
- result[vindex]['data'].append({'x': timestamp, 'y': 0})
- else:
- result[vindex]['data'].append(
- {'x': timestamp, 'y': float(value.text)}
- )
- return result
-
-
-class AverageTraffic(Graphic):
-
- """Average traffic.
- """
- title = ugettext_lazy('Average traffic (msgs/min)')
-
- # Curve definitions
- sent = Curve("sent", "lawngreen", ugettext_lazy("sent messages"))
- recv = Curve("recv", "steelblue", ugettext_lazy("received messages"))
- bounced = Curve("bounced", "yellow", ugettext_lazy("bounced messages"))
- reject = Curve("reject", "tomato", ugettext_lazy("rejected messages"))
-
- order = ['reject', 'bounced', 'recv', 'sent']
-
-
-class AverageTrafficSize(Graphic):
-
- """Average traffic size.
- """
- title = ugettext_lazy('Average normal traffic size (bytes/min)')
-
- # Curve definitions
- size_recv = Curve("size_recv", "orange", ugettext_lazy("received size"))
- size_sent = Curve(
- "size_sent", "mediumturquoise", ugettext_lazy("sent size")
- )
-
-
-class GraphicSet(object):
- title = None
- _graphics = []
-
- def __init__(self):
- self.__ginstances = []
-
- @property
- def html_id(self):
- return self.__class__.__name__.lower()
-
- @property
- def graphics(self):
- if not self.__ginstances:
- self.__ginstances = [graphic() for graphic in self._graphics]
- return self.__ginstances
-
- def get_graphic_names(self):
- return [graphic.display_name for graphic in self._graphics]
-
- def export(self, rrdfile, start, end):
- result = {}
- for graph in self.graphics:
- result[graph.display_name] = {
- "title": graph.title.encode("utf-8"),
- "curves": graph.export(rrdfile, start, end)
- }
- return result
-
-
-class MailTraffic(GraphicSet):
- title = ugettext_lazy('Mail traffic')
- _graphics = [AverageTraffic, AverageTrafficSize]
diff --git a/modoboa/extensions/stats/lib.py b/modoboa/extensions/stats/lib.py
deleted file mode 100644
index 9d78c039f..000000000
--- a/modoboa/extensions/stats/lib.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# coding: utf-8
-import sys
-import time
-
-
-def date_to_timestamp(timetuple):
- """Date conversion.
-
- Returns a date and a time in seconds from the epoch.
-
- :param list timetuple: list containing date
- :return: an integer
- """
- date = " ".join(
- [("%d" % elem) if isinstance(elem, int) else elem for elem in timetuple]
- )
- fmt = "%Y %m %d %H %M %S" \
- if timetuple[1].isdigit() else "%Y %b %d %H %M %S"
- try:
- local = time.strptime(date, fmt)
- except ValueError:
- print >> sys.stderr, "Error: failed to convert date and time"
- return 0
- return int(time.mktime(local))
diff --git a/modoboa/extensions/stats/management/__init__.py b/modoboa/extensions/stats/management/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/stats/management/commands/__init__.py b/modoboa/extensions/stats/management/commands/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/stats/management/commands/logparser.py b/modoboa/extensions/stats/management/commands/logparser.py
deleted file mode 100644
index 1f38ff6fa..000000000
--- a/modoboa/extensions/stats/management/commands/logparser.py
+++ /dev/null
@@ -1,378 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-"""
-Postfix log parser.
-
-This scripts parses a log file produced by postfix (or using the same
-format). It looks for predefined events and build statistics about
-their occurence rate.
-
-At the, somes default graphics are generated using the grapher module.
-(see grapher.py)
-
-Predefined events are:
- * Per domain sent/received messages,
- * Per domain received bad messages (bounced, reject for now),
- * Per domain sent/received traffics size,
- * Global consolidation of all previous events.
-
-"""
-import time
-import sys
-import os
-import re
-import string
-from optparse import make_option
-
-import rrdtool
-
-from django.core.management.base import BaseCommand
-
-from modoboa.core.extensions import exts_pool
-from modoboa.core.management.commands import CloseConnectionMixin
-from modoboa.extensions.admin.models import Domain
-from modoboa.extensions.stats.lib import date_to_timestamp
-from modoboa.lib import parameters
-
-rrdstep = 60
-xpoints = 540
-points_per_sample = 3
-variables = ["sent", "recv", "bounced", "reject", "spam", "virus",
- "size_sent", "size_recv"]
-
-
-class LogParser(object):
-
- def __init__(self, options, workdir, year=None):
- """Constructor
- """
- self.logfile = options["logfile"]
- self.debug = options["debug"]
- self.verbose = options["verbose"]
- try:
- self.f = open(self.logfile)
- except IOError as errno:
- self._dprint("%s" % errno)
- sys.exit(1)
- self.workdir = workdir
- self.__year = year
- self.cfs = ['AVERAGE', 'MAX']
-
- curtime = time.localtime()
- if not self.__year:
- self.__year = curtime.tm_year
- self.curmonth = curtime.tm_mon
-
- self.data = {}
- self.domains = []
- self._load_domain_list()
- self.data["global"] = {}
-
- self.workdict = {}
- self.lupdates = {}
- self._s_date_expr = \
- re.compile(
- r"(?P\w+)\s+(?P\d+)\s+(?P\d+):(?P\d+):(?P\d+)(?P.*)")
- self._hp_date_expr = \
- re.compile(
- r"(?P\d+)-(?P\d+)-(?P\d+)T(?P\d+):(?P\d+):(?P\d+)\.\d+\+\d+:\d+(?P.*)")
- self.date_expr = None
- self.line_expr = \
- re.compile(r"\s+([-\w]+)\s+(\w+)/?\w*[[](\d+)[]]:\s+(.*)")
- self._id_expr = re.compile(r"(\w+): (.*)")
- self._prev_se = -1
- self._prev_mi = -1
- self._prev_ho = -1
- self.cur_t = 0
-
- def _load_domain_list(self):
- """Load the list of allowed domains.
-
- Since the relay domains feature is an extension of the admin
- panel, we don't use an event to get the list of all supported
- domains...
-
- """
- for dom in Domain.objects.all():
- self.domains += [str(dom.name)]
- self.data[str(dom.name)] = {}
- if not exts_pool.is_extension_installed(
- "modoboa.extensions.postfix_relay_domains"):
- return
- from modoboa.extensions.postfix_relay_domains.models import RelayDomain
- for rdom in RelayDomain.objects.all():
- self.domains += [str(rdom.name)]
- self.data[str(rdom.name)] = {}
-
- def _dprint(self, msg):
- """Print a debug message if required.
-
- :param str msg: debug message
- """
- if not self.debug:
- return
- print msg
-
- def _parse_date(self, line):
- """Try to match a date inside :kw:`line` and to convert it to
- a timestamp.
-
- We try different date format until we find valid one. We then
- store it for future use.
-
- :param str line: a log entry
- :return: the remaining part of the line or None
- """
- match = None
- if self.date_expr is None:
- for expr in [self._s_date_expr, self._hp_date_expr]:
- match = expr.match(line)
- if match is not None:
- self.date_expr = expr
- break
- else:
- match = self.date_expr.match(line)
- if match is None:
- return None
- ho = match.group("hour")
- mi = match.group("min")
- se = match.group("sec")
- se = int(int(se) / rrdstep) # rrd step is one-minute => se = 0
- if self._prev_se != se or self._prev_mi != mi or self._prev_ho != ho:
- mo = match.group("month")
- da = match.group("day")
- try:
- ye = match.group("year")
- except IndexError:
- ye = self.year(mo)
- self.cur_t = date_to_timestamp([ye, mo, da, ho, mi, se])
- self.cur_t = self.cur_t - self.cur_t % rrdstep
- self._prev_mi = mi
- self._prev_ho = ho
- self._prev_se = se
- return match.group('eol')
-
- def init_rrd(self, fname, m):
- """init_rrd
-
- Set-up Data Sources (DS)
- Set-up Round Robin Archives (RRA):
- - day,week,month and year archives
- - 2 types : AVERAGE and MAX
-
- parameter : start time
- return : last epoch recorded
- """
- ds_type = 'ABSOLUTE'
- rows = xpoints / points_per_sample
- realrows = int(rows * 1.1) # ensure that the full range is covered
- day_steps = int(3600 * 24 / (rrdstep * rows))
- week_steps = day_steps * 7
- month_steps = week_steps * 5
- year_steps = month_steps * 12
-
- # Set up data sources for our RRD
- params = []
- for v in variables:
- params += ['DS:%s:%s:%s:0:U' % (v, ds_type, rrdstep * 2)]
-
- # Set up RRD to archive data
- for cf in ['AVERAGE', 'MAX']:
- for step in [day_steps, week_steps, month_steps, year_steps]:
- params += ['RRA:%s:0.5:%s:%s' % (cf, step, realrows)]
-
- # With those setup, we can now created the RRD
- rrdtool.create(str(fname),
- '--start', str(m),
- '--step', str(rrdstep),
- *params)
- return m
-
- def update_rrd(self, dom, t):
- """update_rrd
-
- Update RRD with records at t time.
-
- True : if data are up-to-date for current minute
- False : syslog may have probably been already recorded
- or something wrong
- """
- fname = "%s/%s.rrd" % (self.workdir, dom)
- m = t - (t % rrdstep)
- if not os.path.exists(fname):
- self.lupdates[fname] = self.init_rrd(fname, m)
- self._dprint("[rrd] create new RRD file %s" % fname)
- else:
- if fname not in self.lupdates:
- self.lupdates[fname] = rrdtool.last(str(fname))
-
- if m <= self.lupdates[fname]:
- if self.verbose:
- print "[rrd] VERBOSE events at %s already recorded in RRD" % m
- return False
-
- tpl = ""
- for v in variables:
- if tpl != "":
- tpl += ":"
- tpl += v
- # Missing some RRD steps
- # Est ce vraiment nécessaire... ?
- if m > self.lupdates[fname] + rrdstep:
- values = ""
- for v in variables:
- if values != "":
- values += ":"
- values += "0"
- for p in range(self.lupdates[fname] + rrdstep, m, rrdstep):
- if self.verbose:
- print "[rrd] VERBOSE update -t %s %s:%s (SKIP)" \
- % (tpl, p, values)
- rrdtool.update(str(fname), "-t", tpl, "%s:%s" % (p, values))
-
- values = "%s" % m
- tpl = ""
- for v in variables:
- values += ":"
- values += str(self.data[dom][m][v])
- if tpl != "":
- tpl += ":"
- tpl += v
- if self.verbose:
- print "[rrd] VERBOSE update -t %s %s" % (tpl, values)
-
- rrdtool.update(str(fname), "-t", tpl, values)
- self.lupdates[fname] = m
- return True
-
- def initcounters(self, dom):
- init = {}
- for v in variables:
- init[v] = 0
- self.data[dom][self.cur_t] = init
-
- def inc_counter(self, dom, counter, val=1):
- if dom is not None and dom in self.domains:
- if self.cur_t not in self.data[dom]:
- self.initcounters(dom)
- self.data[dom][self.cur_t][counter] += val
-
- if self.cur_t not in self.data["global"]:
- self.initcounters("global")
- self.data["global"][self.cur_t][counter] += val
-
- def year(self, month):
- """Return the appropriate year
-
- Date used in log files don't always embark the year so we need
- to guess it :p
-
- This method tries to deal with year changes in a simply
- (ugly?) way: if we currently are in january and the given
- month is different, return the current year -1. Otherwise,
- return the current year.
-
- Obviously, this method only works for year to year + 1
- changes.
-
- :param month: the month of the current record beeing parsed
- :return: an integer
- """
- month = time.strptime(month, "%b").tm_mon if not month.isdigit() \
- else int(month)
- if self.curmonth == 1 and month != self.curmonth:
- return self.__year - 1
- return self.__year
-
- def _parse_line(self, line):
- """Parse a single log line.
-
- :param str line: log line
- """
- line = self._parse_date(line)
- if line is None:
- return
- m = self.line_expr.match(line)
- if not m:
- return
- host, prog, pid, log = m.groups()
- m = self._id_expr.match(log)
- if m is None:
- self._dprint("Unknown line format: %s" % log)
- return
- (line_id, line_log) = m.groups()
- if line_id == "NOQUEUE":
- addrto = re.match(
- "reject: .*from=<.*> to=<[^@]+@([^>]+)>",
- line_log)
- if addrto and addrto.group(1) in self.domains:
- self.inc_counter(addrto.group(1), 'reject')
- return
- m = re.search("message-id=<([^>]*)>", line_log)
- if m is not None:
- self.workdict[line_id] = {'from': m.group(1), 'size': 0}
- return
- m = re.search("from=<([^>]*)>, size=(\d+)", line_log)
- if m is not None:
- self.workdict[line_id] = {
- 'from': m.group(1), 'size': string.atoi(m.group(2))
- }
- return
-
- m = re.search("to=<([^>]*)>.*status=(\S+)", line_log)
- if m is not None:
- if line_id not in self.workdict:
- self._dprint("Inconsistent mail (%s: %s), skipping"
- % (line_id, m.group(1)))
- return
- if not m.group(2) in variables:
- self._dprint("Unsupported status %s, skipping" % m.group(2))
- return
- addrfrom = re.match("([^@]+)@(.+)", self.workdict[line_id]['from'])
- if addrfrom is not None and addrfrom.group(2) in self.domains:
- self.inc_counter(addrfrom.group(2), 'sent')
- self.inc_counter(addrfrom.group(2), 'size_sent',
- self.workdict[line_id]['size'])
- addrto = re.match("([^@]+)@(.+)", m.group(1))
- domname = addrto.group(2) if addrto is not None else None
- if m.group(2) == "sent":
- self.inc_counter(domname, 'recv')
- self.inc_counter(domname, 'size_recv',
- self.workdict[line_id]['size'])
- else:
- self.inc_counter(domname, m.group(2))
- return
- self._dprint("Unknown line format: %s" % line_log)
-
- def process(self):
- """Process the log file.
-
- We parse it and then generate standard graphics (day, week,
- month).
- """
- for line in self.f.readlines():
- self._parse_line(line)
-
- for dom, data in self.data.iteritems():
- self._dprint("[rrd] dealing with domain %s" % dom)
- for t in sorted(data.keys()):
- self.update_rrd(dom, t)
-
-
-class Command(BaseCommand, CloseConnectionMixin):
- help = 'Log file parser'
-
- option_list = BaseCommand.option_list + (
- make_option("--logfile", default=None,
- help="postfix log in syslog format", metavar="FILE"),
- make_option("--verbose", default=False, action="store_true",
- dest="verbose", help="Set verbose mode"),
- make_option("--debug", default=False, action="store_true",
- help="Set debug mode")
- )
-
- def handle(self, *args, **options):
- if options["logfile"] is None:
- options["logfile"] = parameters.get_admin("LOGFILE", app="stats")
- p = LogParser(options, parameters.get_admin("RRD_ROOTDIR", app="stats"))
- p.process()
diff --git a/modoboa/extensions/stats/modo_extension.py b/modoboa/extensions/stats/modo_extension.py
deleted file mode 100644
index 926063168..000000000
--- a/modoboa/extensions/stats/modo_extension.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# coding: utf-8
-
-"""
-Graphical statistics about emails traffic using RRDtool
-
-This module provides support to retrieve statistics from postfix log :
-sent, received, bounced, rejected
-
-"""
-import sys
-
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.lib import events, parameters
-
-
-class Stats(ModoExtension):
- name = "stats"
- label = "Statistics"
- version = "1.0"
- description = ugettext_lazy(
- "Graphical statistics about emails traffic using RRDtool"
- )
- needs_media = True
-
- def load(self):
- from modoboa.extensions.stats.app_settings import ParametersForm
- events.declare(["GetGraphSets"])
- parameters.register(
- ParametersForm, ugettext_lazy("Graphical statistics")
- )
- from modoboa.extensions.stats import general_callbacks
-
-exts_pool.register_extension(Stats)
diff --git a/modoboa/extensions/stats/static/stats/css/stats.css b/modoboa/extensions/stats/static/stats/css/stats.css
deleted file mode 100644
index edd761be7..000000000
--- a/modoboa/extensions/stats/static/stats/css/stats.css
+++ /dev/null
@@ -1,71 +0,0 @@
-#menubar {
- padding-left: 15px;
-}
-
-.chart {
- position: relative;
- margin-bottom: 20px;
-}
-
-.grid .tick {
- stroke: darkgrey;
- stroke-dasharray: 1, 2;
- opacity: 0.9;
-}
-.grid path {
- stroke-width: 0;
-}
-
-.line_over {
- stroke: darkgrey;
- stroke-width: 1.5px;
- stroke-dasharray: 1, 2;
- display: none;
-}
-
-.axis {
- font-size: 0.7em;
-}
-
-.axis path,
-.axis line {
- fill: none;
- stroke: #000;
- shape-rendering: crispEdges;
-}
-
-.area, .area2 {
- fill-opacity: .6;
-}
-
-.brush .extent {
- stroke: #fff;
- fill-opacity: .125;
- shape-rendering: crispEdges;
-}
-
-.legend rect {
- fill: none;
- stroke: black;
- opacity: 0;
-}
-
-.tip {
- position: absolute;
- z-index: 20;
- top: 60px;
- display: none;
- font-size: 0.9em;
- padding: 5px;
- background: rgba(0, 0, 0, 0.6);
- color: #fff;
- border-radius: 5px;
-}
-
-.tip p {
- margin: 0;
-}
-
-.tracker {
- display: none;
-}
\ No newline at end of file
diff --git a/modoboa/extensions/stats/static/stats/js/d3.legend.js b/modoboa/extensions/stats/static/stats/js/d3.legend.js
deleted file mode 100644
index 52b267a6c..000000000
--- a/modoboa/extensions/stats/static/stats/js/d3.legend.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// d3.legend.js
-// (C) 2012 ziggy.jonsson.nyc@gmail.com
-// MIT licence
-
-(function() {
- d3.legend = function(g, clicked) {
- g.each(function() {
- var g = d3.select(this),
- items = {},
- svg = d3.select(g.property("nearestViewportElement")),
- legendPadding = g.attr("data-style-padding") || 5,
- lb = g.selectAll(".legend-box").data([true]),
- li = g.selectAll(".legend-items").data([true]);
-
- lb.enter().append("rect").classed("legend-box", true);
- li.enter().append("g").classed("legend-items", true);
-
- svg.selectAll("[data-legend]").each(function() {
- var self = d3.select(this);
-
- items[self.attr("data-legend")] = {
- pos: self.attr("data-legend-pos") || this.getBBox().y,
- color: self.attr("data-legend-color") != undefined ? self.attr("data-legend-color") : self.style("fill") != 'none' ? self.style("fill") : self.style("stroke")
- };
- });
-
- items = d3.entries(items).sort(function(a, b) {
- return a.value.pos - b.value.pos;
- });
-
- li.selectAll("text")
- .data(items, function(d) { return d.key; })
- .call(function(d) { d.enter().append("text"); })
- .call(function(d) { d.exit().remove(); })
- .attr("y", function(d, i) { return i + "em"; })
- .attr("x", "1em")
- .text(function(d) { return d.key; });
-
- li.selectAll("circle")
- .data(items, function(d) { return d.key; })
- .call(function(d) { d.enter().append("circle"); })
- .call(function(d) { d.exit().remove(); })
- .attr("cy", function(d, i) { return i - 0.25 + "em"; })
- .attr("cx", 0)
- .attr("r", "4px")
- .style("stroke", function(d) { return d.value.color; })
- .style("stroke-width", "1px")
- .style("stroke-opacity", 0.8)
- .style("fill", function(d) { return d.value.color; })
- .on("click", function(d) {
- var curve = d3.selectAll("[data-legend='" + d.key + "']");
- var state = (curve.style("display") == "none")
- ? "block" : "none";
-
- curve.style("display", state);
- d3.select(this).style(
- "fill", (state == "none") ? "none" : d.value.color
- );
- });
-
- // Reposition and resize the box
- var lbbox = li[0][0].getBBox();
- lb.attr("x", (lbbox.x - legendPadding))
- .attr("y", (lbbox.y - legendPadding))
- .attr("height", (lbbox.height + 2 * legendPadding))
- .attr("width", (lbbox.width + 2 * legendPadding));
- });
- return g;
- };
-})();
diff --git a/modoboa/extensions/stats/static/stats/js/graphic.js b/modoboa/extensions/stats/static/stats/js/graphic.js
deleted file mode 100644
index b650184f3..000000000
--- a/modoboa/extensions/stats/static/stats/js/graphic.js
+++ /dev/null
@@ -1,344 +0,0 @@
-/**
- * Creates an instance of ModoChart.
- *
- * @constructor
- * @this {ModoChart}
- * @param {string} selection add chart to this DOM element.
- *
- */
-function ModoChart(selection) {
- var width = 0,
- height = 300,
- preview_height = 80,
- brush_height = 7,
- margin = {
- left: 50,
- top: 10,
- bottom: 20
- };
- var container;
-
- /**
- * Create and render the chart.
- *
- * @this {ModoChart}
- * @param {Object} data chart's data.
- */
- function my(data) {
- container = d3.select(selection)
- .append("div")
- .attr("class", "chart");
-
- container.append("h6").html(data.title);
- width = $(selection).width();
-
- var svg = container
- .append("svg")
- .attr("width", width)
- .attr("height", my.totalHeight());
-
- svg.append("defs").append("clipPath")
- .attr("id", "clip")
- .append("rect")
- .attr("width", width - 2 * margin.left)
- .attr("height", height + margin.top + margin.bottom);
-
- var x = d3.time.scale().range([0, width - 2 * margin.left]),
- x2 = d3.time.scale().range([0, width - 2 * margin.left]);
- var xAxis = d3.svg.axis().scale(x).orient("bottom"),
- xAxis2 = d3.svg.axis().scale(x2).orient("bottom");
- var y = d3.scale.linear().range([height, 0]),
- y2 = d3.scale.linear().range([preview_height, 0]);
- var yAxis = d3.svg.axis().scale(y).orient("left");
- var bisectDate = d3.bisector(function(d) { return d.x * 1000; }).left;
-
- var brush = d3.svg.brush()
- .x(x2)
- .on("brush", brushed);
-
- x.domain(
- d3.extent(data.curves[0].data.map(function(d) { return d.x * 1000; }))
- );
- y.domain(
- [d3.min(data.curves, function(d) { return d3.min(d.data, function(v) { return v.y; }); }),
- d3.max(data.curves, function(d) { return d3.max(d.data, function(v) { return v.y; }); })
- ]
- );
- x2.domain(x.domain());
- y2.domain(y.domain());
-
- var area = d3.svg.area()
- .interpolate("monotone")
- .x(function(d) { return x(d.x * 1000); })
- .y0(height)
- .y1(function(d) { return y(d.y); });
- var area2 = d3.svg.area()
- .interpolate("monotone")
- .x(function(d) { return x2(d.x * 1000); })
- .y0(preview_height)
- .y1(function(d) { return y2(d.y); });
-
- var focus = svg.append("g")
- .attr("class", "focus")
- .attr("width", width - 2 * margin.left)
- .attr("height", height)
- .attr("pointer-events", "all")
- .attr("transform",
- "translate(" + margin.left + "," + margin.top + ")");
- var context = svg.append("g")
- .attr("class", "context")
- .attr("transform", "translate(" + margin.left + "," + (height + margin.top + margin.bottom + brush_height) + ")");
-
- var curvegroup = focus.append("g")
- .attr('clip-path', 'url(#clip)');
- var curve = curvegroup.selectAll(".curve")
- .data(data.curves)
- .enter().append("g")
- .attr("class", "curve");
- var curve2 = context.selectAll(".curve")
- .data(data.curves)
- .enter().append("g")
- .attr("class", "curve");
-
- /* Vertical line */
- var line = focus.append("line")
- .attr("class", "line_over")
- .attr("x1", 0)
- .attr("y1", 0)
- .attr("x2", 0)
- .attr("y2", height);
-
- /* Custom rectangle to catch mouse events */
- var rect = focus.append("rect")
- .attr("fill", "none")
- .attr("width", width - 2 * margin.left)
- .attr("height", height);
-
- var tooltip = container
- .append("div")
- .attr("class", "remove")
- .attr("class", "tip");
-
- var points = [];
-
- var path = curve.append("path")
- .attr("class", "area")
- .attr("d", function(d, i) {
- var path = this;
-
- points[path] = {};
- d.data.forEach(function(d) {
- points[path][d.x] = d.y;
- });
- focus.append("circle")
- .attr("class", "tracker tracker-" + i)
- .attr("r", 4);
- return area(d.data);
- })
- .attr("data-legend", function(d) { return d.name; })
- .attr("stroke", function(d) { return d.color; })
- .attr("stroke-width", "2px")
- .attr("stroke-opacity", 0.8)
- .style("fill", function(d) { return d.color; });
-
- var xrules = make_x_axis();
-
- focus.append("g")
- .attr("class", "grid")
- .attr("transform", "translate(0," + height + ")")
- .call(xrules);
- focus.append("g")
- .attr("class", "grid")
- .call(make_y_axis);
- focus.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(0," + height + ")")
- .call(xAxis);
- focus.append("g")
- .attr("class", "y axis")
- .call(yAxis);
-
- rect.on("mouseover", function(d) {
- line.style("display", "block");
- tooltip.style("display", "block");
- data.curves.forEach(function(d, cid) {
- var display = d3.selectAll("[data-legend='" + d.name + "']")
- .style("display");
- if (display == "none") {
- return;
- }
- focus.select(".tracker-" + cid).style("display", "block");
- });
- }).on("mousemove", function(d) {
- var mousex = d3.mouse(this)[0],
- mousey = d3.mouse(this)[1];
- var date = x.invert(mousex);
- var text = "";
-
- line.attr("x1", mousex).attr("x2", mousex);
- data.curves.forEach(function(d, cid) {
- var display = d3.selectAll("[data-legend='" + d.name + "']")
- .style("display");
- if (display == "none") {
- return;
- }
- var i = bisectDate(d.data, date.getTime(), 1),
- d0 = d.data[i - 1],
- d1 = d.data[i],
- point = date.getTime() - (d0.x * 1000) > (d1.x * 1000) - date.getTime() ? d1 : d0;
- text += "" + d.name + ": " + point.y.toFixed(3) + "
";
-
- var tracker_x = x(point.x * 1000),
- tracker_y = y(point.y);
-
- focus.selectAll(".tracker-" + cid)
- .style("fill", d.color)
- .attr("cx", tracker_x)
- .attr("cy", tracker_y);
- });
- if (mousex + tooltip[0][0].clientWidth >= width - 2 * margin.left) {
- var left = mousex - (tooltip[0][0].clientWidth - (margin.left - 20));
- tooltip.style("left", left + "px");
- } else {
- tooltip.style("left", (mousex + margin.left + 20) + "px");
- }
- tooltip.html("" + date + "
" + text);
- }).on("mouseout", function(d) {
- tooltip.style("display", "none");
- line.style("display", "none");
- focus.selectAll(".tracker").style("display", "none");
- });
-
- var legend = focus.append("g")
- .attr("class", "legend")
- .attr("transform", "translate(50,10)")
- .style("font-size", "0.8em")
- .call(d3.legend);
-
- curve2.append("path")
- .attr("class", "area2")
- .attr("d", function(d) { return area2(d.data); })
- .attr("stroke", function(d) { return d.color; })
- .attr("stroke-width", "2px")
- .attr("stroke-opacity", 0.8)
- .attr("data-legend", function(d) { return d.name; })
- .style("fill", function(d) { return d.color; });
-
- context.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(0," + preview_height + ")")
- .call(xAxis2);
-
- context.append("g")
- .attr("class", "grid")
- .attr("transform", "translate(0," + preview_height + ")")
- .call(make_preview_x_axis);
-
- context.append("g")
- .attr("class", "x brush")
- .call(brush)
- .selectAll("rect")
- .attr("y", -6)
- .attr("height", preview_height + brush_height);
-
- function make_x_axis() {
- return d3.svg.axis()
- .scale(x)
- .orient("bottom")
- .ticks(6)
- .tickSize(-height, 0, 0)
- .tickFormat("");
- }
-
- function make_y_axis() {
- return d3.svg.axis()
- .scale(y)
- .orient("left")
- .ticks(6)
- .tickSize(-(width - 2 * margin.left), 0, 0)
- .tickFormat("");
- }
-
- function make_preview_x_axis() {
- return d3.svg.axis()
- .scale(x2)
- .orient("bottom")
- .ticks(6)
- .tickSize(-preview_height, 0, 0)
- .tickFormat("");
- }
-
- function brushed() {
- x.domain(brush.empty() ? x2.domain() : brush.extent());
- focus.selectAll(".area")
- .attr("d", function(d) { return area(d.data); });
- focus.select(".x.axis").call(xAxis);
- focus.select(".grid").call(xrules);
- }
- }
-
- /**
- * Set or get chart's width.
- *
- * @this {ModoChart}
- * @param {integer} value new width.
- * @return {number} current width.
- */
- my.width = function(value) {
- if (!arguments.length) return width;
- width = value;
- return my;
- };
-
- /**
- * Set or get chart's height.
- *
- * @this {ModoChart}
- * @param {integer} value new height.
- * @return {number} current height.
- */
- my.height = function(value) {
- if (!arguments.length) return height;
- height = value;
- return my;
- };
-
- /**
- * Set or get chart's margin.
- *
- * @this {ModoChart}
- * @param {Object} value new margin.
- * @return {Object} current margin.
- */
- my.margin = function(value) {
- if (!arguments.length) return margin;
- margin = value;
- return my;
- };
-
- /**
- * Compute and return chart's total height.
- *
- * @this {ModoChart}
- * @return {integer} total height.
- */
- my.totalHeight = function() {
- return height + 2 * margin.top
- + 2 * margin.bottom + preview_height
- + brush_height;
- };
-
- /**
- * Update the chart with new data.
- *
- * @this {ModoChart}
- * @param {Object} data new data
- */
- my.update = function(data) {
- container.select("svg").remove();
- $(container[0][0]).empty();
- my(data);
- };
-
- return my;
-}
diff --git a/modoboa/extensions/stats/static/stats/js/stats.js b/modoboa/extensions/stats/static/stats/js/stats.js
deleted file mode 100644
index 5258aecd1..000000000
--- a/modoboa/extensions/stats/static/stats/js/stats.js
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * Create an instance of Stats.
- *
- * @constructor
- */
-var Stats = function(options) {
- this.initialize(options);
-};
-
-Stats.prototype = {
- constructor: Stats,
-
- defaults: {
- deflocation: "graphs/",
- language: "en",
- domain_list_url: null
- },
-
- initialize: function(options) {
- this.options = $.extend({}, this.defaults, options);
- this.options.defcallback = $.proxy(this.charts_cb, this);
-
- var navobj = new History(this.options);
- this.navobj = navobj;
-
- if (navobj.params.searchquery !== undefined) {
- $("#searchquery").val(navobj.params.searchquery);
- }
- $("#searchquery").focus(function() {
- var $this = $(this);
- if ($this.val() === undefined) {
- return;
- }
- $this.data("oldvalue", $this.val());
- $this.val("");
- }).blur(function() {
- var $this = $(this);
- if ($this.val() === "") {
- if ($this.data("oldvalue")) {
- $this.val($this.data('oldvalue'));
- $this.data("oldvalue", null);
- } else {
- $this.val(gettext("Search a domain"));
- }
- }
- });
- if (navobj.params.start) {
- $("#id_from").val(navobj.params.start);
- }
- if (navobj.params.end) {
- $("#id_to").val(navobj.params.end);
- }
- if (navobj.params.period) {
- $("input[data-period={0}]".format(navobj.params.period))
- .attr("checked", true)
- .parent().addClass("active");
- if (navobj.params.period == "custom") {
- $("#custom_period").removeClass("hidden");
- }
- }
- $("#custom-period .datetime_picker").datetimepicker({
- format: 'YYYY-MM-DD hh:mm:ss',
- language: this.options.language
- });
- $("#searchquery").autocompleter({
- choices: $.proxy(this.get_domain_list, this),
- choice_selected: $.proxy(this.search_domain, this),
- empty_choice: $.proxy(this.reset_search, this)
- });
-
- this.register_nav_callbacks();
- this.listen();
- },
-
- listen: function() {
- $(".period_selector").click($.proxy(this.change_period, this));
- $("#customsend").on("click", $.proxy(this.custom_period, this));
- $(window).resize($.proxy(this.resize_charts, this));
- },
-
- register_nav_callbacks: function() {
- this.navobj.register_callback("graphs",
- $.proxy(this.charts_cb, this));
- },
-
- /**
- * Retrieve a list of domain from the server.
- */
- get_domain_list: function() {
- var result;
-
- $.ajax({
- url: this.options.domain_list_url,
- dataType: "json",
- async: false
- }).done(function(data) {
- result = data;
- });
- return result;
- },
-
- change_period: function(e) {
- e.preventDefault();
- var $link = $(e.target).children("input");
- var period = $link.attr("data-period");
-
- if (period != "custom") {
- $("#custom_period").addClass("hidden");
- this.navobj.delparam("start").delparam("end");
- this.navobj.setparam("period", $link.attr("data-period")).update();
- } else {
- $("#custom_period").removeClass("hidden");
- }
- },
-
- /**
- * Update all charts on resize event.
- *
- * @this {Stats}
- */
- resize_charts: function() {
- var data = this.data;
- $.each(this.charts, function(id, mychart) {
- mychart.update(data.graphs[id]);
- });
- },
-
- /**
- * Create or update charts.
- *
- * @this {Stats}
- * @param {Object} data
- */
- charts_cb: function(data) {
- var menuid = "menu_" + this.navobj.getparam("gset");
-
- $("#" + menuid).addClass("active");
- this.data = data;
- if (this.charts !== undefined) {
- $.each(this.charts, function(id, mychart) {
- mychart.update(data.graphs[id]);
- });
- } else {
- this.charts = {};
- $.each(data.graphs, $.proxy(function(id, graphdef) {
- var mychart = ModoChart("#gset");
- this.charts[id] = mychart;
- mychart(graphdef);
- }, this));
- }
- },
-
- search_domain: function(value) {
- this.navobj.setparam("searchquery", value).update();
- },
-
- reset_search: function() {
- $("#searchquery").data("oldvalue", null);
- this.navobj.delparam("searchquery").update();
- },
-
- custom_period: function(e) {
- e.preventDefault();
- var $fromdate = $("#id_from");
- var $todate = $("#id_to");
-
- if ($fromdate.val() === "" || $todate.val() === "") {
- return;
- }
- this.navobj.setparams({
- period: "custom",
- start: $fromdate.val(),
- end: $todate.val()
- }).update();
- }
-};
diff --git a/modoboa/extensions/stats/templates/stats/index.html b/modoboa/extensions/stats/templates/stats/index.html
deleted file mode 100644
index 08e583a8b..000000000
--- a/modoboa/extensions/stats/templates/stats/index.html
+++ /dev/null
@@ -1,89 +0,0 @@
-{% extends "twocols.html" %}{% load i18n %}{% load url from future %}
-{% load static %}
-
-{% block pagetitle %}{% trans "Graphical statistics" %}{% endblock %}
-
-{% block extra_css %}
-
-{% endblock %}
-
-{% block extra_js %}
-
-
-
-
-
-
-
-{% endblock %}
-
-{% block leftcol %}
-
-{% endblock %}
-
-{% block apparea %}
-
-
-
-
-
-
-
-
- {% trans "Apply" %}
-
-
-
-
-
-
- {% for id, gset in graph_sets.items %}
-
- {% endfor %}
-
-
-{% endblock %}
diff --git a/modoboa/extensions/stats/urls.py b/modoboa/extensions/stats/urls.py
deleted file mode 100644
index 00bbad712..000000000
--- a/modoboa/extensions/stats/urls.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from django.conf.urls import patterns, url
-
-
-urlpatterns = patterns(
- 'modoboa.extensions.stats.views',
-
- url(r'^$', 'index', name='fullindex'),
- url(r'^graphs/$', "graphs", name="graph_list"),
- url(r'^domains/$', "get_domain_list", name="domain_list"),
-)
diff --git a/modoboa/extensions/stats/views.py b/modoboa/extensions/stats/views.py
deleted file mode 100644
index de88d898c..000000000
--- a/modoboa/extensions/stats/views.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# coding: utf-8
-
-"""Custom views."""
-
-import re
-import time
-from django.shortcuts import render
-from django.utils.translation import ugettext as _
-from django.contrib.auth.decorators import (
- login_required, user_passes_test, permission_required
-)
-
-from modoboa.core.extensions import exts_pool
-from modoboa.lib import events
-from modoboa.lib.exceptions import BadRequest, PermDeniedException, NotFound
-from modoboa.lib.web_utils import (
- render_to_json_response
-)
-from modoboa.extensions.admin.models import (
- Domain
-)
-from modoboa.extensions.stats.lib import date_to_timestamp
-
-
-@login_required
-@permission_required("admin.view_mailboxes")
-def index(request):
- """
- FIXME: how to select a default graph set ?
- """
- deflocation = "graphs/?gset=mailtraffic"
- if not request.user.is_superuser:
- if not Domain.objects.get_for_admin(request.user).count():
- raise NotFound(_("No statistics available"))
-
- graph_sets = events.raiseDictEvent('GetGraphSets')
- periods = [
- {"name": "day", "label": _("Day")},
- {"name": "week", "label": _("Week")},
- {"name": "month", "label": _("Month")},
- {"name": "year", "label": _("Year")},
- {"name": "custom", "label": _("Custom")}
- ]
- return render(request, 'stats/index.html', {
- "periods": periods,
- "selection": "stats",
- "deflocation": deflocation,
- "graph_sets": graph_sets
- })
-
-
-def check_domain_access(user, pattern):
- """Check if an administrator can access a domain/relay domain.
-
- If a non super administrator asks for the global view, we give him
- a view on the first domain he manage instead.
-
- :return: a domain name (str) or None.
- """
- targets = [Domain]
- if exts_pool.is_extension_installed(
- "modoboa.extensions.postfix_relay_domains"):
- from modoboa.extensions.postfix_relay_domains.models import RelayDomain
- targets.append(RelayDomain)
-
- if pattern in [None, "global"]:
- if not user.is_superuser:
- for target in targets:
- if not target.objects.get_for_admin(user).count():
- continue
- return target.objects.get_for_admin(user)[0].name
- return None
- return "global"
-
- for target in targets:
- results = target.objects.filter(name__startswith=pattern)
- if results.count() != 1:
- continue
- if not user.can_access(results[0]):
- raise PermDeniedException
- return results[0].name
- return None
-
-
-@login_required
-@user_passes_test(lambda u: u.group != "SimpleUsers")
-def graphs(request):
- gset = request.GET.get("gset", None)
- gsets = events.raiseDictEvent("GetGraphSets")
- if gset not in gsets:
- raise NotFound(_("Unknown graphic set"))
- searchq = request.GET.get("searchquery", None)
- period = request.GET.get("period", "day")
- tplvars = dict(graphs={}, period=period)
- domain = check_domain_access(request.user, searchq)
- if domain is None:
- return render_to_json_response({})
- tplvars["domain"] = domain
-
- if period == "custom":
- if "start" not in request.GET or "end" not in request.GET:
- raise BadRequest(_("Bad custom period"))
- start = request.GET["start"]
- end = request.GET["end"]
- expr = re.compile(r'[:\- ]')
- period_name = "%s_%s" % (expr.sub('', start), expr.sub('', end))
- start = date_to_timestamp(expr.split(start))
- end = date_to_timestamp(expr.split(end))
- else:
- end = int(time.mktime(time.localtime()))
- start = "-1%s" % period
- period_name = period
-
- tplvars['graphs'] = gsets[gset].export(tplvars["domain"], start, end)
- tplvars["period_name"] = period_name
- tplvars["start"] = start
- tplvars["end"] = end
-
- return render_to_json_response(tplvars)
-
-
-@login_required
-@user_passes_test(lambda u: u.group != "SimpleUsers")
-def get_domain_list(request):
- """Get the list of domains (and relay domains) the user can see."""
- doms = [dom.name for dom in Domain.objects.get_for_admin(request.user)]
- if exts_pool.is_extension_installed(
- "modoboa.extensions.postfix_relay_domains"):
- from modoboa.extensions.postfix_relay_domains.models import RelayDomain
- doms += [
- rdom.name for rdom in
- RelayDomain.objects.get_for_admin(request.user)
- ]
- return render_to_json_response(doms)
From a434286e208657d24d648a0c9ac965ce51cf1588 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Feb 2015 13:59:49 +0100
Subject: [PATCH 06/25] Remove sievefilters extension.
---
modoboa/extensions/sievefilters/__init__.py | 0
.../extensions/sievefilters/app_settings.py | 65 ----
modoboa/extensions/sievefilters/forms.py | 322 -----------------
.../sievefilters/general_callbacks.py | 32 --
modoboa/extensions/sievefilters/lib.py | 107 ------
.../extensions/sievefilters/modo_extension.py | 24 --
.../static/sievefilters/css/style.css | 134 -------
.../sievefilters/js/jquery.dynfields.js | 339 ------------------
.../static/sievefilters/js/lib.js | 243 -------------
.../templates/sievefilters/filter.html | 26 --
.../templates/sievefilters/guieditor.html | 25 --
.../templates/sievefilters/index.html | 104 ------
.../templates/sievefilters/rawfilter.html | 6 -
.../sievefilters/templatetags/__init__.py | 0
.../templatetags/sfilters_tags.py | 179 ---------
modoboa/extensions/sievefilters/test.py | 42 ---
modoboa/extensions/sievefilters/urls.py | 29 --
modoboa/extensions/sievefilters/views.py | 337 -----------------
18 files changed, 2014 deletions(-)
delete mode 100644 modoboa/extensions/sievefilters/__init__.py
delete mode 100644 modoboa/extensions/sievefilters/app_settings.py
delete mode 100644 modoboa/extensions/sievefilters/forms.py
delete mode 100644 modoboa/extensions/sievefilters/general_callbacks.py
delete mode 100644 modoboa/extensions/sievefilters/lib.py
delete mode 100644 modoboa/extensions/sievefilters/modo_extension.py
delete mode 100644 modoboa/extensions/sievefilters/static/sievefilters/css/style.css
delete mode 100644 modoboa/extensions/sievefilters/static/sievefilters/js/jquery.dynfields.js
delete mode 100644 modoboa/extensions/sievefilters/static/sievefilters/js/lib.js
delete mode 100644 modoboa/extensions/sievefilters/templates/sievefilters/filter.html
delete mode 100644 modoboa/extensions/sievefilters/templates/sievefilters/guieditor.html
delete mode 100644 modoboa/extensions/sievefilters/templates/sievefilters/index.html
delete mode 100644 modoboa/extensions/sievefilters/templates/sievefilters/rawfilter.html
delete mode 100644 modoboa/extensions/sievefilters/templatetags/__init__.py
delete mode 100644 modoboa/extensions/sievefilters/templatetags/sfilters_tags.py
delete mode 100644 modoboa/extensions/sievefilters/test.py
delete mode 100644 modoboa/extensions/sievefilters/urls.py
delete mode 100644 modoboa/extensions/sievefilters/views.py
diff --git a/modoboa/extensions/sievefilters/__init__.py b/modoboa/extensions/sievefilters/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/sievefilters/app_settings.py b/modoboa/extensions/sievefilters/app_settings.py
deleted file mode 100644
index c3d1cbb4d..000000000
--- a/modoboa/extensions/sievefilters/app_settings.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# coding: utf-8
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from sievelib.managesieve import SUPPORTED_AUTH_MECHS
-from modoboa.lib.parameters import AdminParametersForm, UserParametersForm
-from modoboa.lib.form_utils import SeparatorField, YesNoField, InlineRadioSelect
-
-
-def supported_auth_mechs():
- values = [('AUTO', 'auto')]
- for m in SUPPORTED_AUTH_MECHS:
- values += [(m, m.lower())]
- return values
-
-
-class ParametersForm(AdminParametersForm):
- app = "sievefilters"
-
- sep1 = SeparatorField(label=_("ManageSieve settings"))
-
- server = forms.CharField(
- label=_("Server address"),
- initial="127.0.0.1",
- help_text=_("Address of your MANAGESIEVE server"),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- port = forms.IntegerField(
- label=_("Server port"),
- initial=4190,
- help_text=_("Listening port of your MANAGESIEVE server"),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- starttls = YesNoField(
- label=_("Connect using STARTTLS"),
- initial="no",
- help_text=_("Use the STARTTLS extension")
- )
-
- authentication_mech = forms.ChoiceField(
- label=_("Authentication mechanism"),
- choices=supported_auth_mechs(),
- initial="auto",
- help_text=_("Prefered authentication mechanism"),
- widget=forms.Select(attrs={"class": "form-control"})
- )
-
-
-class UserSettings(UserParametersForm):
- app = "sievefilters"
-
- sep1 = SeparatorField(label=_("General"))
-
- editor_mode = forms.ChoiceField(
- initial="gui",
- label=_("Editor mode"),
- choices=[("raw", "raw"), ("gui", "simplified")],
- help_text=_("Select the mode you want the editor to work in"),
- widget=InlineRadioSelect(attrs={"type": "checkbox"})
- )
-
- @staticmethod
- def has_access(user):
- return user.mailbox_set.count() != 0
diff --git a/modoboa/extensions/sievefilters/forms.py b/modoboa/extensions/sievefilters/forms.py
deleted file mode 100644
index 01e91e98c..000000000
--- a/modoboa/extensions/sievefilters/forms.py
+++ /dev/null
@@ -1,322 +0,0 @@
-"""Custom forms."""
-
-from django import forms
-from django.forms.widgets import RadioFieldRenderer, RadioSelect, RadioInput
-from django.http import QueryDict
-from django.utils.encoding import force_unicode
-from django.utils.html import conditional_escape
-from django.utils.safestring import mark_safe
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from modoboa.extensions.admin.templatetags.admin_tags import gender
-
-
-class FiltersSetForm(forms.Form):
- name = forms.CharField(
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
- active = forms.BooleanField(
- label=gender("Active", "m"), required=False,
- initial=False,
- help_text=ugettext_lazy("Check to activate this filters set")
- )
-
-
-class CustomRadioInput(RadioInput):
-
- def __unicode__(self):
- return self.render()
-
- def render(self, name=None, value=None, attrs=None, choices=()):
- name = name or self.name
- value = value or self.value
- attrs = attrs or self.attrs
- if 'id' in self.attrs:
- label_for = ' for="%s_%s"' % (self.attrs['id'], self.index)
- else:
- label_for = ''
- choice_label = conditional_escape(force_unicode(self.choice_label))
- return mark_safe(
- u'%s %s '
- % (label_for, self.tag(), choice_label)
- )
-
-
-class CustomRadioFieldRenderer(RadioFieldRenderer):
-
- def __iter__(self):
- for i, choice in enumerate(self.choices):
- yield CustomRadioInput(
- self.name, self.value, self.attrs.copy(), choice, i)
-
- def __getitem__(self, idx):
- choice = self.choices[idx]
- return CustomRadioInput(
- self.name, self.value, self.attrs.copy(), choice, idx)
-
- def render(self):
- return mark_safe(u'\n'.join([force_unicode(w) for w in self]))
-
-
-class CustomRadioSelect(RadioSelect):
- renderer = CustomRadioFieldRenderer
-
-
-class FilterForm(forms.Form):
-
- def __init__(self, conditions, actions, request, *args, **kwargs):
- super(FilterForm, self).__init__(*args, **kwargs)
-
- self.field_widths = {
- "match_type": 8
- }
-
- self.fields["name"] = forms.CharField(label=_("Name"))
- self.fields["match_type"] = forms.ChoiceField(
- choices=[("allof", _("All of the following")),
- ("anyof", _("Any of the following")),
- ("all", _("All messages"))],
- initial="anyof",
- widget=CustomRadioSelect()
- )
-
- self.header_operators = [
- ("contains", _("contains"), "string"),
- ("notcontains", _("does not contain"), "string"),
- ("is", _("is"), "string"),
- ("isnot", _("is not"), "string")
- ]
-
- self.cond_templates = [
- {"name": "Subject",
- "label": _("Subject"),
- "operators": self.header_operators},
- {"name": "From",
- "label": _("Sender"),
- "operators": self.header_operators},
- {"name": "To",
- "label": _("Recipient"),
- "operators": self.header_operators},
- {"name": "Cc",
- "label": _("Cc"),
- "operators": self.header_operators},
- {"name": "size", "label": _("Size"),
- "operators": [("over", _("is greater than"), "number"),
- ("under", _("is less than"), "number")]},
- ]
-
- self.action_templates = [
- {"name": "fileinto", "label": _("Move message to"),
- "args": [{"type": "list", "vloader": "userfolders"}]},
- {"name": "redirect", "label": _("Redirect message to"),
- "args": [{"type": "string"}]},
- ]
-
- self.conds_cnt = 0
- for c in conditions:
- getattr(self, "_build_%s_field" % c[0])(c[1], c[2])
- self.actions_cnt = 0
- for a in actions:
- getattr(self, "_build_%s_field" % a[0])(request, a[1])
-
- def clean_name(self):
- """Check that name does not contain strange chars.
- """
- if '#' in self.cleaned_data["name"]:
- raise forms.ValidationError(_("Wrong filter name"))
- return self.cleaned_data["name"]
-
- def _build_header_field(self, name, op, value):
- targets = []
- ops = []
- vfield = None
- for tpl in self.cond_templates:
- targets += [(tpl["name"], tpl["label"]), ]
- if tpl["name"] != name:
- continue
- for opdef in tpl["operators"]:
- ops += [opdef[:2]]
- if op != opdef[0]:
- continue
- if opdef[2] in ["string", "number"]:
- vfield = forms.CharField(max_length=255, initial=value)
-
- self.fields["cond_target_%d" % self.conds_cnt] = \
- forms.ChoiceField(initial=name, choices=targets)
- self.fields["cond_operator_%d" % self.conds_cnt] = \
- forms.ChoiceField(initial=op, choices=ops)
- self.fields["cond_value_%d" % self.conds_cnt] = vfield
- self.conds_cnt += 1
-
- def _build_Subject_field(self, op, value):
- self._build_header_field("Subject", op, value)
-
- def _build_To_field(self, op, value):
- self._build_header_field("To", op, value)
-
- def _build_From_field(self, op, value):
- self._build_header_field("From", op, value)
-
- def _build_Cc_field(self, op, value):
- self._build_header_field("Cc", op, value)
-
- def _build_size_field(self, op, value):
- self._build_header_field("size", op, value)
-
- def _build_action_field(self, request, name, value):
- actions = []
- args = None
- for tpl in self.action_templates:
- actions += [(tpl["name"], tpl["label"]), ]
- if name == tpl["name"]:
- args = tpl["args"]
- self.fields["action_name_%d" % self.actions_cnt] = \
- forms.ChoiceField(initial=name, choices=actions)
- for cnt in xrange(0, len(args)):
- arg = args[cnt]
- aname = "action_arg_%d_%d" % (self.actions_cnt, cnt)
- if arg["type"] == "string":
- self.fields[aname] = forms.CharField(
- max_length=255,
- initial=value)
- elif arg["type"] == "list":
- choices = getattr(self, arg["vloader"])(request)
- self.fields[aname] = forms.ChoiceField(
- initial=value,
- choices=choices)
- self.actions_cnt += 1
-
- def _build_redirect_field(self, request, value):
- self._build_action_field(request, "redirect", value)
-
- def _build_fileinto_field(self, request, value):
- self._build_action_field(request, "fileinto", value)
-
- def __build_folders_list(self, folders, user, imapc, parentmb=None):
- ret = []
- for fd in folders:
- value = fd["path"] if "path" in fd else fd["name"]
- if parentmb:
- ret += [
- (value, fd["name"].replace(
- "%s%s" % (parentmb, imapc.hdelimiter), ""))
- ]
- else:
- ret += [(value, fd["name"])]
- if "sub" in fd:
- submboxes = imapc.getmboxes(user, value, unseen_messages=False)
- ret += self.__build_folders_list(submboxes, user, imapc, value)
- return ret
-
- def userfolders(self, request):
- from modoboa.extensions.webmail.lib import get_imapconnector
-
- mbc = get_imapconnector(request)
- ret = mbc.getmboxes(request.user, unseen_messages=False)
-
- folders = self.__build_folders_list(ret, request.user, mbc)
- return folders
-
- def tofilter(self):
- conditions = []
- actions = []
- for cpt in xrange(0, self.conds_cnt):
- conditions += [(self.cleaned_data["cond_target_%d" % cpt],
- ":" + self.cleaned_data["cond_operator_%d" % cpt],
- self.cleaned_data["cond_value_%d" % cpt])]
- for cpt in xrange(0, self.actions_cnt):
- naction = (self.cleaned_data["action_name_%d" % cpt],)
- argcpt = 0
- while True:
- try:
- naction += (
- self.cleaned_data[
- "action_arg_%d_%d" %
- (cpt, argcpt)],)
- except KeyError:
- break
- argcpt += 1
- actions += [naction]
-
- return (conditions, actions)
-
-
-def build_filter_form_from_qdict(request):
- conditions = []
- actions = []
- qdict = QueryDict("", mutable=True)
- qdict["name"] = request.POST["name"]
- qdict["match_type"] = request.POST["match_type"]
- cpt = 0
- i = 0
- if qdict["match_type"] != "all":
- while True:
- if cpt == int(request.POST["conds"]):
- break
- if "cond_target_%d" % i in request.POST:
- qdict["cond_target_%d" % cpt] = (
- request.POST["cond_target_%d" % i]
- )
- qdict["cond_operator_%d" % cpt] = (
- request.POST["cond_operator_%d" % i]
- )
- qdict["cond_value_%d" % cpt] = request.POST["cond_value_%d" % i]
- condtarget = request.POST["cond_target_%d" % i]
- condop = request.POST["cond_operator_%d" % i]
- condvalue = request.POST["cond_value_%d" % i]
- conditions += [(condtarget, condop, condvalue)]
- cpt += 1
- i += 1
- cpt = 0
- i = 0
- while True:
- if cpt == int(request.POST["actions"]):
- break
- if "action_name_%d" % i in request.POST:
- qdict["action_name_%d" % cpt] = request.POST["action_name_%d" % i]
- action = request.POST["action_name_%d" % i]
- argcpt = 0
- args = []
- while True:
- try:
- qdict["action_arg_%d_%d" % (cpt, argcpt)] = \
- request.POST["action_arg_%d_%d" % (i, argcpt)]
- args += [request.POST["action_arg_%d_%d" % (i, argcpt)]]
- except KeyError:
- break
- argcpt += 1
- args = [action] + args
- actions += [args]
- cpt += 1
- i += 1
-
- return FilterForm(conditions, actions, request, qdict)
-
-
-def build_filter_form_from_filter(request, name, fobj):
- from sievelib.commands import SizeCommand, TrueCommand
-
- match_type = fobj["test"].name
- conditions = []
- for t in fobj["test"]["tests"]:
- if isinstance(t, TrueCommand):
- match_type = "all"
- conditions += [("Subject", "contains", "")]
- break
- elif isinstance(t, SizeCommand):
- conditions += [("size", t["comparator"][1:], t["limit"])]
- else:
- conditions += [(t["header-names"].strip('"'),
- t["match-type"][1:],
- t["key-list"].strip('"'))]
- actions = []
- for c in fobj.children:
- action = (c.name,)
- for arg in c.args_definition:
- action += (c[arg["name"]].strip('"'),)
- actions += [action]
-
- form = FilterForm(conditions, actions, request)
- form.fields["name"].initial = name
- form.fields["match_type"].initial = match_type
- return form
diff --git a/modoboa/extensions/sievefilters/general_callbacks.py b/modoboa/extensions/sievefilters/general_callbacks.py
deleted file mode 100644
index c09b73fc4..000000000
--- a/modoboa/extensions/sievefilters/general_callbacks.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from django.utils.translation import ugettext as _
-from django.core.urlresolvers import reverse
-from modoboa.lib import events
-
-
-@events.observe("UserMenuDisplay")
-def menu(target, user):
- if target != "options_menu":
- return []
- if not user.mailbox_set.count():
- return []
- return [
- {"name": "sievefilters",
- "label": _("Message filters"),
- "url": reverse("sievefilters:index"),
- "img": "fa fa-filter"}
- ]
-
-
-@events.observe("UserLogout")
-def userlogout(request):
- from .lib import SieveClient
-
- if not request.user.mailbox_set.count():
- return
- try:
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- except Exception:
- pass
- else:
- sc.logout()
diff --git a/modoboa/extensions/sievefilters/lib.py b/modoboa/extensions/sievefilters/lib.py
deleted file mode 100644
index 26cf8a2d1..000000000
--- a/modoboa/extensions/sievefilters/lib.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# coding: utf-8
-
-"""Internal tools."""
-
-from sievelib.factory import FiltersSet
-from sievelib.managesieve import Client, Error
-from sievelib.parser import Parser
-
-from django.utils.translation import ugettext as _
-
-from modoboa.lib import parameters
-from modoboa.lib.connections import ConnectionsManager, ConnectionError
-from modoboa.lib.exceptions import ModoboaException
-
-
-class SieveClientError(ModoboaException):
- http_code = 424
-
-
-class SieveClient(object):
- __metaclass__ = ConnectionsManager
-
- def __init__(self, user=None, password=None):
- try:
- ret, msg = self.login(user, password)
- except Error as e:
- raise ConnectionError(str(e))
- if not ret:
- raise ConnectionError(msg)
-
- def login(self, user, password):
- self.msc = Client(parameters.get_admin("SERVER"),
- int(parameters.get_admin("PORT")),
- debug=False)
- use_starttls = True if parameters.get_admin("STARTTLS") == "yes" \
- else False
- authmech = parameters.get_admin("AUTHENTICATION_MECH")
- if authmech == "AUTO":
- authmech = None
- try:
- ret = self.msc.connect(user, password, use_starttls, authmech)
- except Error:
- ret = False
- if not ret:
- return False, _(
- "Connection to MANAGESIEVE server failed, check your "
- "configuration"
- )
- return True, None
-
- def logout(self):
- self.msc.logout()
- self.msc = None
-
- def refresh(self, user, password):
- import ssl
-
- if self.msc is not None:
- try:
- self.msc.capability()
- except Error as e:
- pass
- else:
- return
- try:
- ret, msg = self.login(user, password)
- except (Error, ssl.SSLError) as e:
- raise ConnectionError(e)
- if not ret:
- raise ConnectionError(msg)
-
- def listscripts(self):
- return self.msc.listscripts()
-
- def getscript(self, name, format="raw"):
- content = self.msc.getscript(name)
- if content is None:
- raise SieveClientError(self.msc.errmsg)
- if format == "raw":
- return content
- p = Parser()
- if not p.parse(content):
- print "Parse error????"
- return None
- fs = FiltersSet(name)
- fs.from_parser_result(p)
- return fs
-
- def pushscript(self, name, content, active=False):
- if isinstance(content, unicode):
- content = content.encode("utf-8")
- if not self.msc.havespace(name, len(content)):
- error = "%s (%s)" % (
- _("Not enough space on server"), self.msc.errmsg)
- raise SieveClientError(error)
- if not self.msc.putscript(name, content):
- raise SieveClientError(self.msc.errmsg)
- if active and not self.msc.setactive(name):
- raise SieveClientError(self.msc.errmsg)
-
- def deletescript(self, name):
- if not self.msc.deletescript(name):
- raise SieveClientError(self.msc.errmsg)
-
- def activatescript(self, name):
- if not self.msc.setactive(name):
- raise SieveClientError(self.msc.errmsg)
diff --git a/modoboa/extensions/sievefilters/modo_extension.py b/modoboa/extensions/sievefilters/modo_extension.py
deleted file mode 100644
index 0b4fe46ba..000000000
--- a/modoboa/extensions/sievefilters/modo_extension.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# coding: utf-8
-"""Declare and register the sievefilters extension."""
-
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.lib import parameters
-
-
-class SieveFilters(ModoExtension):
- name = "sievefilters"
- label = "Sieve filters"
- version = "1.0"
- description = ugettext_lazy("Plugin to easily create server-side filters")
- url = "sfilters"
- available_for_topredirection = True
-
- def load(self):
- from .app_settings import ParametersForm, UserSettings
- parameters.register(ParametersForm, ugettext_lazy("Sieve filters"))
- parameters.register(UserSettings, ugettext_lazy("Message filters"))
- from modoboa.extensions.sievefilters import general_callbacks
-
-exts_pool.register_extension(SieveFilters)
diff --git a/modoboa/extensions/sievefilters/static/sievefilters/css/style.css b/modoboa/extensions/sievefilters/static/sievefilters/css/style.css
deleted file mode 100644
index 6ff656c85..000000000
--- a/modoboa/extensions/sievefilters/static/sievefilters/css/style.css
+++ /dev/null
@@ -1,134 +0,0 @@
-.fset_container {
- padding: 0 15px;
-}
-
-#set_content textarea {
- width: 100%;
- height: 500px;
-}
-
-#set_content label {
- margin: 5px;
-}
-
-#filters_list {
- border-left: 1px solid #CCC;
- position: absolute;
- padding-left: 5px;
- left: 190px;
- right: 10px;
- top: 0px;
- bottom: 0px;
-}
-
-#id_content {
- width: 95% !important;
- height: 270px;
-}
-
-/* Filter form */
-#filterform {
- margin: 7px;
-}
-
-#filterform h2 {
- margin: 0;
- padding: 0;
- font-size: 1em;
- margin-top: 20px;
-}
-
-#submit_container {
- width: 100%;
- position: absolute;
- bottom: 5px;
- text-align: center;
-}
-
-#error {
- white-space: pre-line;
-}
-
-#addfilterlist {
- background-color: #FAFAFA;
- border: 1px solid #CCCCCC;
- border-radius: 26px 26px 26px 26px;
- padding: 14px 5px 5px;
-}
-
-#matchtype {
- font-size: 0.9em;
-}
-
-
-div.item {
- margin-bottom: 10px;
- margin-left: 5px;
- overflow: auto;
-}
-
-ul.errors {
- list-style: none;
- display: inline;
- margin: 0;
- padding: 0;
-}
-
-.errors li {
- color: red;
- font-weight: bold;
- font-size: 0.9em;
- display: inline;
-}
-
-.leftbox {
- width: 155px;
-}
-
-.leftbox h1 {
- float: none !important;
- padding: 0;
- margin: 0;
- font-size: 1.1em;
-}
-
-.leftbox ul {
- list-style: none;
- padding: 5px 0 0 0;
- margin: 0;
-}
-
-.leftbox li {
- margin: 5px 0;
-}
-
-.leftbox a, .leftbox a:visited {
- color: black;
- text-decoration: none;
-}
-
-.leftbox a:hover {
- color: #6AB0C5;
- text-decoration: none;
-}
-
-.leftbox li.selected {
- background-color: #FFFF77;
-}
-
-.leftbox img {
- float: left;
- margin-right: 5px;
-}
-
-a.green {
- text-decoration: none;
- font-weight: bold;
- color: green;
-}
-
-a.red {
- text-decoration: none;
- font-weight: bold;
- color: red;
-}
\ No newline at end of file
diff --git a/modoboa/extensions/sievefilters/static/sievefilters/js/jquery.dynfields.js b/modoboa/extensions/sievefilters/static/sievefilters/js/jquery.dynfields.js
deleted file mode 100644
index 1b6c8a253..000000000
--- a/modoboa/extensions/sievefilters/static/sievefilters/js/jquery.dynfields.js
+++ /dev/null
@@ -1,339 +0,0 @@
-(function($) {
- var DynamicCondition = function(element, options) {
- this.$element = $(element);
- this.options = $.extend({}, $.fn.dyncondition.defaults, options);
- this.fields_cnt = 1;
- this.nextid = 1;
-
- var $addlink = $(' ', {
- href: '#',
- id: this.$element.attr("id") + '_rmbtn',
- html: ' '
- });
- $("select[name*=cond_target_]").change($.proxy(this.target_change, this));
- $addlink.click($.proxy(this.addfields, this));
- this.$element.append($addlink);
-
- for (var cpt = 1; true; cpt++) {
- var $div = $("#condition_" + cpt);
-
- if (!$div.length) {
- break;
- }
- $div.append(this.newrmlink());
- this.nextid++;
- this.fields_cnt++;
- }
- };
-
- DynamicCondition.prototype = {
- constructor: DynamicCondition,
-
- loadoperators: function($container, tpl) {
- $container.empty();
- for (var ocpt = 0; ocpt < tpl.operators.length; ocpt++) {
- var $opt = $(" ", {
- value: tpl["operators"][ocpt][0],
- html: tpl["operators"][ocpt][1]
- });
-
- $container.append($opt);
- }
- },
-
- removefields: function(e) {
- var $link = $(e.target).parent();
- var id = $link.attr("id");
-
- e.preventDefault();
- $("#" + id.replace("_rmbtn", "")).remove();
- this.fields_cnt--;
- },
-
- newrmlink: function() {
- return $(' ', {
- href: '#',
- id: 'condition_' + this.nextid + '_rmbtn',
- html: ' '
- }).click($.proxy(this.removefields, this));
- },
-
- addfields: function(e) {
- e.preventDefault();
- var $div = $("
", {
- id: "condition_" + this.nextid, 'class': "item"
- });
- var $condtarget = $(" ", {
- id: "id_cond_target_" + this.nextid,
- name: "cond_target_" + this.nextid,
- class: "form-control element-inline-block"
- }).change($.proxy(this.target_change, this));
- var $condoperator = $(" ", {
- id: "id_cond_operator_" + this.nextid,
- name: "cond_operator_" + this.nextid,
- class: "form-control element-inline-block"
- });
- var $condvalue = $(" ", {
- id: "id_cond_value_" + this.nextid,
- name: "cond_value_" + this.nextid,
- type: "text",
- class: "form-control element-inline-block"
- });
- var $rmlink = this.newrmlink();
-
- for (var cpt = 0; cpt < this.options.templates.length; cpt++) {
- var tpl = this.options.templates[cpt];
- var $opt = $(" ", {
- value: tpl.name,
- html: tpl.label
- });
-
- $condtarget.append($opt);
- if (tpl.name != this.options.defaultcond) {
- continue;
- }
- this.loadoperators($condoperator, tpl);
- }
-
- $div.append($condtarget, $condoperator, $condvalue, $rmlink);
- $condtarget.wrap('
');
- $condoperator.wrap('
');
- $condvalue.wrap('
');
- this.$element.after($div);
- this.nextid++;
- this.fields_cnt++;
- },
-
- target_change: function(e) {
- var $target = $(e.target);
- var parts = $target.attr("name").split("_");
- var $container = $("#id_cond_operator_" + parts[2]);
-
- for (var cpt = 0; cpt < this.options.templates.length; cpt++) {
- var tpl = this.options.templates[cpt];
-
- if (tpl.name != $target.val()) {
- continue;
- }
- this.loadoperators($container, tpl);
- break;
- }
- },
-
- counter: function() {
- return this.fields_cnt;
- }
- };
-
- $.fn.dyncondition = function(method) {
- return this.each(function() {
- var $this = $(this),
- data = $this.data('dyncondition'),
- options = typeof method === "object" && method;
-
- if (!data) {
- $this.data('dyncondition', new DynamicCondition(this, options));
- }
- if (typeof method === "string") {
- data[method]();
- }
- });
- };
-
- $.fn.dyncondition.defaults = {
- defaultcond: "Subject",
- templates: []
- };
-
-})(jQuery);
-
-/*
- * Dynamic actions class
- */
-(function($) {
- var DynamicAction = function(element, options) {
- this.$element = $(element);
- this.options = $.extend({}, $.fn.dynaction.defaults, options);
- this.nextid = 1;
- this.fields_cnt = 1;
-
- var $addlink = $(' ', {
- href: '#',
- id: this.$element.attr("id") + '_rmbtn',
- html: ' '
- });
- $("select[name*=action_name_]").change($.proxy(this.name_change, this));
- $addlink.click($.proxy(this.addfields, this));
- this.$element.append($addlink);
-
- for (var cpt = 1; true; cpt++) {
- var $div = $("#action_" + cpt);
-
- if (!$div.length) {
- break;
- }
- $div.append(this.newrmlink());
- this.nextid++;
- this.fields_cnt++;
- }
-
- $("#id_action_arg_0_0").find("option").each(function() {
- var $this = $(this),
- cpt = 1,
- start = 0,
- value = $this.val();
-
- while (true) {
- var id = value.indexOf(options.hdelimiter, start);
- if (id == -1) {
- break;
- }
- $this.css("margin-left", (cpt * 20) + "px");
- cpt++;
- start = id + 1;
- }
- });
-
- this.$fdoptions = $("#id_action_arg_0_0").find("option");
- };
-
- DynamicAction.prototype = {
- constructor: DynamicAction,
-
- loadargs: function(id, tpl) {
- var res = [];
-
- for (var acpt = 0; acpt < tpl.args.length; acpt++) {
- var argname = "action_arg_" + id + "_" + acpt;
- var $child = null;
-
- if (tpl.args[acpt].type == "list") {
- $child = $(" ", {id: "id_" + argname, name: argname, class: "form-control"});
- if (tpl.args[acpt].vloader != undefined) {
- this[tpl.args[acpt].vloader]($child);
- }
- } else if (tpl.args[acpt].type == "string") {
- $child = $(" ", {
- type: "text",
- id: "id_" + argname,
- name: argname,
- class: "form-control"
- });
- }
- res.push($child);
- }
- return res;
- },
-
- deletePrevArgs: function(id) {
- for (var cpt = 0; true; cpt++) {
- var $arg = $("#id_action_arg_" + id + "_" + cpt);
- if (!$arg.length) {
- break;
- }
- $arg.remove();
- }
- },
-
- name_change: function(e) {
- var $target = $(e.target);
- var parts = $target.attr("name").split("_");
- var $pos = $("#action_" + parts[2] + "_rmbtn");
-
- e.preventDefault();
- this.deletePrevArgs(parts[2]);
- for (var cpt = 0; cpt < this.options.templates.length; cpt++) {
- var tpl = this.options.templates[cpt];
- if (tpl.name != $target.val()) {
- continue;
- }
- $.each(this.loadargs(parts[2], tpl), function(idx, arg) {
- $pos.before(arg);
- });
- }
- },
-
- newrmlink: function() {
- return $(' ', {
- href: '#',
- id: 'action_' + this.nextid + '_rmbtn',
- html: ' '
- }).click($.proxy(this.removefields, this));
- },
-
- addfields: function(e) {
- e.preventDefault();
- var $div = $("
", {id: "action_" + this.nextid, "class": "item"});
- var $actioname = $(" ", {
- id: "id_action_name_" + this.nextid,
- name: "action_name_" + this.nextid,
- class: "form-control element-inline-block"
- });
- var $rmlink = this.newrmlink();
- var args = null;
-
- for (var cpt = 0; cpt < this.options.templates.length; cpt++) {
- var tpl = this.options.templates[cpt];
- var $opt = $(" ", {
- value: tpl.name,
- html: tpl.label
- });
-
- $actioname.append($opt);
- if (tpl.name != this.options.defaultaction) {
- continue;
- }
- args = this.loadargs(this.nextid, tpl);
- }
- $div.append($actioname);
- $actioname.change($.proxy(this.name_change, this));
- $.each(args, function(idx, element) {
- $div.append(element);
- element.wrap('
');
- });
-
- $actioname.wrap('
');
- $div.append($rmlink);
- this.$element.after($div);
- this.nextid++;
- this.fields_cnt++;
- },
-
- removefields: function(e) {
- var $link = $(e.target).parent();
- var id = $link.attr("id");
-
- e.preventDefault();
- $("#" + id.replace("_rmbtn", "")).remove();
- this.fields_cnt--;
- },
-
- userfolders: function($container) {
- this.$fdoptions.each(function() {
- $container.append($(this).clone());
- });
- }
-
- };
-
- $.fn.dynaction = function(method) {
- return this.each(function() {
- var $this = $(this),
- data = $this.data('dynaction'),
- options = typeof method === "object" && method;
-
- if (!data) {
- $this.data('dynaction', new DynamicAction(this, options));
- }
- if (typeof method === "string") {
- data[method]();
- }
- });
- };
-
- $.fn.dynaction.defaults = {
- defaultaction: "fileinto",
- hdelimiter: '.',
- templates: []
- };
-})(jQuery);
\ No newline at end of file
diff --git a/modoboa/extensions/sievefilters/static/sievefilters/js/lib.js b/modoboa/extensions/sievefilters/static/sievefilters/js/lib.js
deleted file mode 100644
index 9edd81f62..000000000
--- a/modoboa/extensions/sievefilters/static/sievefilters/js/lib.js
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Plugin : "Sieve filters"
- *
- * Javascript utilities
- */
-var curscript = null;
-
-/*
- * Remove a filter from a filters set.
- *
- */
-function removefilter(evt) {
- evt.preventDefault();
- if (!confirm(gettext("Remove this filter?"))) {
- return;
- }
- var $this = $(this);
-
- $.ajax({
- url: $this.attr("href"),
- dataType: 'json'
- }).done(function(response) {
- histomanager.update(true);
- $("body").notify('success', response, 2000);
- });
-}
-
-/*
- * Handler listening for the "change" event on the filters sets list.
- */
-function changefs(evt) {
- evt.preventDefault();
- histomanager.baseurl($(this).val()).update();
-}
-
-/*
- * Initializes buttons located inside the filters list
- */
-function init_filters_list() {
- $("a[name=togglestate]").click(toggle_filter_state);
- $("a[name*=movefilter_]").click(move_filter);
- $("a[name=removefilter]").click(removefilter);
-}
-
-/*
- * Function called just after a new filters set has been loaded.
- *
- * It updates the middle DIV and initializes the user interface.
- */
-function loadfs(response) {
- curscript = histomanager.getbaseurl();
- $("#curfset").val(curscript);
- $("#set_content").html(response.content);
-
- if ($("#filters_list") != undefined) {
- init_filters_list();
- }
- if ($("#fsetmenu").length) {
- $("#fsetmenu").remove();
- }
- $("#menu").after($(response.menu));
- $("a[name=activatefs]").click(activatefs);
- $("a[name=savefs]").click(savefs);
- $("a[name=removefs]").click(removefs);
-}
-
-/*
- * Common function to send a command that manipulates a filters set.
- *
- * (remove, activate)
- */
-function send_command(cmd, extracb) {
- $.ajax({
- url: cmd,
- dataType: 'json'
- }).done(function(response) {
- if (extracb != undefined) {
- extracb(response);
- }
- if (!response.norefresh) {
- histomanager.update(true);
- }
- $("body").notify('success', response.respmsg, 2000);
- });
-}
-
-/*
- * Common utility used by filters set manipulation functions to
- * validate any new asked action. (activate, save, remove)
- */
-function check_prereqs(evt, msg) {
- evt.preventDefault();
- if (!curscript) {
- return false;
- }
- if (msg != undefined && !confirm(msg)) {
- return false;
- }
- return true;
-}
-
-/*
- * Save the current filters set by applying the modifications to the
- * server.
- */
-function savefs(evt) {
- if (!check_prereqs(evt, gettext("Save changes?"))) {
- return;
- }
- var $editor = $("#feditor");
-
- $.ajax({
- url: $editor.attr("action"),
- type: $editor.attr("method"),
- dataType: 'json',
- data: $editor.serialize()
- }).done(function(response) {
- $("body").notify('success', response.respmsg, 2000);
- });
-}
-
-/*
- * Remove the current filters set.
- *
- * On success, the user will be automatically redirected to the active
- * filters set.
- */
-function removefs(evt) {
- if (!check_prereqs(evt, gettext("Remove filters set?"))) {
- return;
- }
- send_command($(this).attr("href"), function(response) {
- var $curfset = $("#curfset");
-
- $curfset.find("option[value='" + curscript + "']").remove();
- histomanager.baseurl(response.newfs, 1);
- });
-}
-
-/*
- * Activate the current filters set.
- */
-function activatefs(evt) {
- var $this = $(this);
-
- if (!check_prereqs(evt, gettext("Activate this filters set?"))) {
- return;
- }
- send_command($this.attr("href"), function(response) {
- $("#curfset").find("option").each(function(index, element) {
- var $element = $(element);
-
- ($element.val() == curscript)
- ? $element.html(curscript + " (" + gettext("active") + ")")
- : $element.html($element.val());
- });
- });
-}
-
-/*
- * Enable/Disable a specific filter
- */
-function toggle_filter_state(event) {
- var $this = $(this);
-
- event.preventDefault();
- $.ajax({
- url: $this.attr("href"),
- dataType: 'json'
- }).done(function(response) {
- $this.html(response.label);
- $this.attr("class", "");
- $this.addClass(response.color);
- });
-}
-
-function move_filter(event) {
- var $this = $(this);
-
- event.preventDefault();
- $.ajax({
- url: $this.attr('href'),
- dataType: 'json'
- }).done(function(response) {
- $("#set_content").html(response.content);
- init_filters_list();
- });
-}
-
-function filterset_created(data) {
- var name = data.url;
- var option = $('' + name + ' ');
- var curfset = $(parent.document).find("#curfset");
-
- curfset.append(option);
- curfset.val(name);
-
- if (data.active) {
- curfset.find("option").each(function(index, element) {
- var $element = $(element);
-
- if ($element.val() == name) {
- $element.html(name + " (" + gettext("active") + ")");
- } else {
- $element.html($element.val());
- }
- });
- }
- histomanager.baseurl(data.url, 1).update(1);
-}
-
-function filtersetform_cb() {
- $("#newfiltersset").find("input").keypress(function(e) {
- if (e.which == 13) e.preventDefault();
- });
- $(".submit").on('click', function(e) {
- simple_ajax_form_post(e, {
- formid: "newfiltersset",
- reload_on_success: false,
- success_cb: filterset_created
- });
- });
-}
-
-/*
- * From here: specific functions used by the user-friendly form to
- * create/edit filters.
- */
-function fetch_templates(url, container) {
- if (container) {
- return container;
- }
- var result;
-
- $.ajax({
- url: url,
- async: false,
- dataType: 'json'
- }).done(function(data) {
- result = data;
- });
- return result;
-}
diff --git a/modoboa/extensions/sievefilters/templates/sievefilters/filter.html b/modoboa/extensions/sievefilters/templates/sievefilters/filter.html
deleted file mode 100644
index e0476c0b4..000000000
--- a/modoboa/extensions/sievefilters/templates/sievefilters/filter.html
+++ /dev/null
@@ -1,26 +0,0 @@
-{% extends "common/generic_modal_form.html" %}
-{% load i18n form_tags sfilters_tags %}
-
-{% block modal_css_classes %}modal-lg{% endblock %}
-
-{% block formbody %}
- {% if oldname %} {% endif %}
- {% render_field form.name %}
- {% trans "Conditions" %}
-
-
- {% render_field form.match_type %}
-
-
- {% for ec in conds_nb %}
- {% display_condition form ec %}
- {% endfor %}
-
-
- {% trans "Actions" %}
-
- {% for ea in actions_nb %}
- {% display_action form ea %}
- {% endfor %}
-
-{% endblock %}
diff --git a/modoboa/extensions/sievefilters/templates/sievefilters/guieditor.html b/modoboa/extensions/sievefilters/templates/sievefilters/guieditor.html
deleted file mode 100644
index d73924118..000000000
--- a/modoboa/extensions/sievefilters/templates/sievefilters/guieditor.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% load i18n sfilters_tags %}{% load url from future %}
-{% if fs.filters %}
-
-
- {% trans "Actions" %}
- {% trans "Name" %}
- {% trans "Active" %}
-
- {% for filter in fs.filters %}
-
- {% filter_actions fs.name filter forloop.counter forloop.last %}
- {{ filter.name }}
-
-
- {{ filter.enabled|yesno }}
-
-
-
- {% endfor %}
-
-{% else %}
-{% trans "No filter defined yet" %}
-{% endif %}
diff --git a/modoboa/extensions/sievefilters/templates/sievefilters/index.html b/modoboa/extensions/sievefilters/templates/sievefilters/index.html
deleted file mode 100644
index 40d3482ba..000000000
--- a/modoboa/extensions/sievefilters/templates/sievefilters/index.html
+++ /dev/null
@@ -1,104 +0,0 @@
-{% extends "twocols.html" %}{% load i18n sfilters_tags %}{% load url from future %}
-{% load static %}
-
-{% block pagetitle %}{% trans "Message filters" %}{% endblock %}
-
-{% block extra_css %}
-
-{% endblock %}
-
-{% block extra_js %}
-
-
-
-
-
-{% endblock %}
-
-{% block leftcol %}
-
-{% endblock %}
-
-{% block apparea %}
-
- {% if not active_script and not scripts %}
-
{% trans "No filters set defined yet. You must create one in order to define filters." %}
- {% endif %}
-
-{% endblock %}
diff --git a/modoboa/extensions/sievefilters/templates/sievefilters/rawfilter.html b/modoboa/extensions/sievefilters/templates/sievefilters/rawfilter.html
deleted file mode 100644
index 301f70161..000000000
--- a/modoboa/extensions/sievefilters/templates/sievefilters/rawfilter.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% load url from future %}
-{% csrf_token %}
- {{ scriptcontent }}
-
-
diff --git a/modoboa/extensions/sievefilters/templatetags/__init__.py b/modoboa/extensions/sievefilters/templatetags/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py b/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py
deleted file mode 100644
index 3bc0f937f..000000000
--- a/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py
+++ /dev/null
@@ -1,179 +0,0 @@
-from django import template
-from django.core.urlresolvers import reverse
-from django.template.loader import render_to_string
-from django.utils.translation import ugettext as _
-
-from modoboa.lib.web_utils import render_actions
-from modoboa.lib.templatetags.form_tags import configure_field_classes
-
-register = template.Library()
-
-
-@register.simple_tag
-def sfilters_menu(user):
- entries = [
- {"name": "newfilterset",
- "img": "fa fa-plus",
- "label": _("New filters set"),
- "url": reverse("sievefilters:fs_add"),
- "modal": True,
- "modalcb": "filtersetform_cb"
- }
- ]
-
- return render_to_string('common/menulist.html',
- {"entries": entries, "user": user})
-
-
-@register.simple_tag
-def fset_menu(mode, setname):
- entries = []
- if mode == "gui":
- entries += [
- {"name": "newfilter",
- "img": "fa fa-plus",
- "label": _("New filter"),
- "url": reverse("sievefilters:filter_add",
- args=[setname]),
- "modal": True,
- "autowidth": True,
- "modalcb": "filterform_cb"}
- ]
- if mode == "raw":
- entries += [
- {"name": "savefs",
- "img": "fa fa-download-alt",
- "label": _("Save filters set"),
- "url": reverse("sievefilters:fs_save",
- args=[setname])},
- ]
-
- entries += [
- {"name": "activatefs",
- "img": "fa fa-check",
- "label": _("Activate filters set"),
- "url": reverse("sievefilters:fs_activate",
- args=[setname])},
- {"name": "removefs",
- "img": "fa fa-trash",
- "label": _("Remove filters set"),
- "url": reverse("sievefilters:fs_delete", args=[setname])},
- {"name": "downloadfs",
- "img": "fa fa-download",
- "label": _("Download"),
- "url": reverse("sievefilters:fs_download", args=[setname])}
- ]
-
- return render_to_string('common/menulist.html',
- {"entries": entries})
-
-
-@register.simple_tag
-def filter_actions(setname, f, position, islast):
- actions = [
- {"name": "editfilter",
- "url": reverse(
- "sievefilters:filter_change", args=[setname, f["name"]]),
- "img": "fa fa-edit",
- "title": _("Edit filter"),
- "modal": True,
- "autowidth": True,
- "modalcb": "filterform_cb"},
- {"name": "removefilter",
- "url": reverse(
- "sievefilters:filter_delete", args=[setname, f["name"]]),
- "img": "fa fa-trash",
- "title": _("Remove this filter")}
- ]
- if position != 1:
- actions += [
- {"name": "movefilter_up",
- "url": reverse(
- "sievefilters:filter_move_up", args=[setname, f["name"]]),
- "img": "fa fa-chevron-up",
- "title": _("Move this filter up")}
- ]
- if not islast:
- actions += [
- {"name": "movefilter_down",
- "url": reverse(
- "sievefilters:filter_move_down", args=[setname, f["name"]]),
- "img": "fa fa-chevron-down",
- "title": _("Move this filter down")},
- ]
- return render_actions(actions)
-
-
-@register.simple_tag
-def display_errors(errors):
- if not len(errors):
- return ""
- t = template.Template("""
-
- {% for error in errors %}
- {{ error|safe }}
- {% endfor %}
-
-""")
- return t.render(template.Context({
- "errors": errors
- }))
-
-
-@register.simple_tag
-def display_condition(form, cnt):
- target = form["cond_target_%d" % cnt]
- configure_field_classes(target)
- operator = form["cond_operator_%d" % cnt]
- configure_field_classes(operator)
- value = form["cond_value_%d" % cnt]
- configure_field_classes(value)
- t = template.Template("""
-
-
{{ tfield }}
-
{{ofield}}
-
{{ vfield }}
- {{ verrors }}
-
-""")
- return t.render(template.Context({
- "idx": cnt,
- "tfield": target,
- "ofield": operator,
- "vfield": value,
- "verrors": display_errors(value.errors)
- }))
-
-
-@register.simple_tag
-def display_action(form, cnt):
- action = form["action_name_%d" % cnt]
- configure_field_classes(action)
- values = []
- acnt = 0
- verrors = []
- while True:
- try:
- field = form["action_arg_%d_%d" % (cnt, acnt)]
- configure_field_classes(field)
- values += [field]
- if field.errors:
- verrors += field.errors
- acnt += 1
- except KeyError:
- break
- t = template.Template("""
-
-
- {{ afield }}
-
- {% for v in values %}
-
{{ v }}
- {% endfor %}{{ verrors }}
-
-""")
- return t.render(template.Context({
- "idx": cnt,
- "afield": action, "values": values,
- "verrors": display_errors(verrors)
- }))
diff --git a/modoboa/extensions/sievefilters/test.py b/modoboa/extensions/sievefilters/test.py
deleted file mode 100644
index 9d35832dc..000000000
--- a/modoboa/extensions/sievefilters/test.py
+++ /dev/null
@@ -1,42 +0,0 @@
-if __name__ == "__main__":
- clt = ManageSieveClient("mail.koalabs.org", 2000)
- if clt.connect("tonio@ngyn.org", "aka/12;c", starttls=True):
- print clt.get_sasl_mechanisms()
- print clt.get_sieve_capabilities()
- print clt.havespace("test", 45)
-
- if not clt.putscript("myscript", """require ["fileinto", "envelope"];
-
-if envelope :contains "to" "tmartin+sent" {
- fileinto "INBOX.sent";
-}
-"""):
- print clt.errmsg
-
- if not clt.putscript("test", """#comment
-InvalidSieveCommand
-"""):
- print clt.errmsg
-
- clt.deletescript("thescript")
-
- if not clt.setactive("myscript"):
- print clt.errmsg
- print clt.listscripts()
-
- sc = clt.getscript("myscript")
- if sc is None:
- print clt.errmsg
- else:
- print sc
-
- if not clt.renamescript("myscript", "thescript"):
- print clt.errmsg
-
- clt.setactive("")
-
- if not clt.deletescript("thescript"):
- print clt.errmsg
- else:
- print clt.errmsg
- clt.logout()
diff --git a/modoboa/extensions/sievefilters/urls.py b/modoboa/extensions/sievefilters/urls.py
deleted file mode 100644
index 70f3f4262..000000000
--- a/modoboa/extensions/sievefilters/urls.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns(
- 'modoboa.extensions.sievefilters.views',
-
- url(r'^$', 'index', name="index"),
- url(r'^savefs/(?P.+)/$', 'savefs', name="fs_save"),
- url(r'^newfs/$', 'new_filters_set', name="fs_add"),
- url(r'^removefs/(?P.+)/$', 'remove_filters_set', name="fs_delete"),
- url(r'^activatefs/(?P.+)/$', 'activate_filters_set',
- name="fs_activate"),
- url(r'^downloadfs/(?P.+)/$', 'download_filters_set',
- name="fs_download"),
- url(r'^templates/(?P\w+)/$', 'get_templates',
- name="templates_get"),
- url(r'^(?P.+)/newfilter/$', 'newfilter',
- name="filter_add"),
- url(r'^(?P.+)/editfilter/(?P.+)/$', 'editfilter',
- name="filter_change"),
- url(r'^(?P.+)/removefilter/(?P.+)/$', 'removefilter',
- name="filter_delete"),
- url(r'^(?P.+)/togglestate/(?P.+)/$',
- 'toggle_filter_state', name="filter_toggle_state"),
- url(r'^(?P.+)/moveup/(?P.+)/$',
- 'move_filter_up', name="filter_move_up"),
- url(r'^(?P.+)/movedown/(?P.+)/$',
- 'move_filter_down', name="filter_move_down"),
- url(r'^(?P.+)/$', 'getfs', name="fs_get"),
-)
diff --git a/modoboa/extensions/sievefilters/views.py b/modoboa/extensions/sievefilters/views.py
deleted file mode 100644
index 2a97b479b..000000000
--- a/modoboa/extensions/sievefilters/views.py
+++ /dev/null
@@ -1,337 +0,0 @@
-# coding: utf-8
-
-"""Custom views."""
-
-from rfc6266 import build_header
-from sievelib.commands import BadArgument, BadValue
-from sievelib.managesieve import Error
-
-from django.contrib.auth.decorators import login_required
-from django.core.urlresolvers import reverse
-from django.http import HttpResponse
-from django.shortcuts import render
-from django.template.loader import render_to_string
-from django.utils.translation import ugettext as _
-
-from .forms import (
- FilterForm, build_filter_form_from_qdict, build_filter_form_from_filter,
- FiltersSetForm
-)
-from .lib import SieveClient, SieveClientError
-from .templatetags.sfilters_tags import fset_menu
-from modoboa.extensions.admin.lib import needs_mailbox
-from modoboa.lib import parameters
-from modoboa.lib.connections import ConnectionError
-from modoboa.lib.exceptions import BadRequest
-from modoboa.lib.web_utils import (
- _render_error, ajax_response, render_to_json_response
-)
-
-
-@login_required
-@needs_mailbox()
-def index(request, tplname="sievefilters/index.html"):
- from modoboa.extensions.webmail.lib import get_imapconnector
-
- try:
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- except ConnectionError as e:
- return _render_error(request, user_context={"error": e})
-
- try:
- active_script, scripts = sc.listscripts()
- except Error as e:
- return _render_error(request, user_context={"error": e})
-
- if active_script is None:
- active_script = ""
- default_script = "%s/" % scripts[0] if len(scripts) else ""
- else:
- default_script = "%s/" % active_script
- return render(request, tplname, {
- "selection": "user",
- "active_script": active_script,
- "default_script": default_script,
- "scripts": sorted(scripts),
- "hdelimiter": get_imapconnector(request).hdelimiter
- })
-
-
-@login_required
-@needs_mailbox()
-def get_templates(request, ftype):
- if ftype == "condition":
- return render_to_json_response(
- FilterForm([], [], request).cond_templates
- )
- return render_to_json_response(
- FilterForm([], [], request).action_templates
- )
-
-
-@login_required
-@needs_mailbox()
-def getfs(request, name):
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- editormode = parameters.get_user(request.user, "EDITOR_MODE")
- error = None
- try:
- content = sc.getscript(name, format=editormode)
- except SieveClientError as e:
- error = str(e)
- else:
- if content is None:
- error = _("Failed to retrieve filters set")
-
- if error is not None:
- return ajax_response(request, "ko", respmsg=error)
-
- if editormode == "raw":
- htmlcontent = render_to_string("sievefilters/rawfilter.html", dict(
- name=name, scriptcontent=content
- ))
- else:
- htmlcontent = render_to_string("sievefilters/guieditor.html", dict(
- fs=content
- ))
-
- menu = '' % \
- (_("Actions"), fset_menu(editormode, name))
- resp = dict(menu=menu, content=htmlcontent)
- return render_to_json_response(resp)
-
-
-def build_filter_ctx(ctx, form):
- ctx["form"] = form
- ctx["conds_nb"] = range(form.conds_cnt)
- ctx["actions_nb"] = range(form.actions_cnt)
- return ctx
-
-
-def submitfilter(
- request, setname, okmsg, tplname, tplctx, update=False, sc=None):
- form = build_filter_form_from_qdict(request)
- if form.is_valid():
- if sc is None:
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- fset = sc.getscript(setname, format="fset")
- conditions, actions = form.tofilter()
- match_type = form.cleaned_data["match_type"]
- if match_type == "all":
- match_type = "anyof"
- conditions = [("true",)]
- fltname = form.cleaned_data["name"].encode("utf-8")
- try:
- if not update:
- fset.addfilter(fltname, conditions, actions,
- match_type)
- else:
- oldname = request.POST["oldname"].encode("utf-8")
- fset.updatefilter(
- oldname, fltname, conditions, actions, match_type
- )
- except (BadArgument, BadValue) as inst:
- raise BadRequest(str(inst))
- sc.pushscript(fset.name, str(fset))
- return render_to_json_response(okmsg)
-
- return render_to_json_response({'form_errors': form.errors}, status=400)
-
-
-@login_required
-@needs_mailbox()
-def newfilter(request, setname, tplname="sievefilters/filter.html"):
- ctx = dict(
- title=_("New filter"),
- formid="filterform",
- action=reverse("sievefilters:filter_add", args=[setname]),
- action_label=_("Create"),
- action_classes="submit"
- )
- if request.method == "POST":
- return submitfilter(
- request, setname, _("Filter created"), tplname, ctx
- )
-
- conds = [("Subject", "contains", "")]
- actions = [("fileinto", "")]
- form = FilterForm(conds, actions, request)
- ctx = build_filter_ctx(ctx, form)
- return render(request, tplname, ctx)
-
-
-@login_required
-@needs_mailbox()
-def editfilter(request, setname, fname, tplname="sievefilters/filter.html"):
- ctx = dict(
- title=_("Edit filter"),
- formid="filterform",
- action=reverse("sievefilters:filter_change", args=[setname, fname]),
- action_label=_("Update"),
- action_classes="submit"
- )
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- if request.method == "POST":
- return submitfilter(
- request, setname, _("Filter modified"), tplname, ctx,
- update=True, sc=sc
- )
-
- fset = sc.getscript(setname, format="fset")
- if isinstance(fname, unicode):
- fname = fname.encode("utf-8")
- f = fset.getfilter(fname)
- form = build_filter_form_from_filter(request, fname, f)
- ctx = build_filter_ctx(ctx, form)
- ctx["oldname"] = fname
- ctx["hidestyle"] = "none" \
- if form.fields["match_type"].initial == "all" else "block"
- return render(request, tplname, ctx)
-
-
-@login_required
-@needs_mailbox()
-def removefilter(request, setname, fname):
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- fset = sc.getscript(setname, format="fset")
- if fset.removefilter(fname.encode("utf-8")):
- sc.pushscript(fset.name, str(fset))
- return render_to_json_response(_("Filter removed"))
- return render_to_json_response(_("Failed to remove filter"), status=500)
-
-
-@login_required
-@needs_mailbox()
-def savefs(request, name):
- if "scriptcontent" not in request.POST:
- return
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- try:
- sc.pushscript(name, request.POST["scriptcontent"])
- except SieveClientError as e:
- error = str(e)
- return ajax_response(request, "ko", respmsg=error)
- return ajax_response(request, respmsg=_("Filters set saved"))
-
-
-@login_required
-@needs_mailbox()
-def new_filters_set(request, tplname="common/generic_modal_form.html"):
- if request.method == "POST":
- form = FiltersSetForm(request.POST)
- if form.is_valid():
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- sc.pushscript(form.cleaned_data["name"], "# Empty script",
- form.cleaned_data["active"])
- return render_to_json_response({
- "url": form.cleaned_data["name"],
- "active": form.cleaned_data["active"],
- "respmsg": _("Filters set created")
- })
- return render_to_json_response({'form_errors': form.errors}, status=400)
-
- ctx = {"title": _("Create a new filters set"),
- "formid": "newfiltersset",
- "action_label": _("Create"),
- "action_classes": "submit",
- "action": reverse("sievefilters:fs_add"),
- "withmenu": False,
- "withunseen": False,
- "form": FiltersSetForm()}
- return render(request, tplname, ctx)
-
-
-@login_required
-@needs_mailbox()
-def remove_filters_set(request, name):
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- sc.deletescript(name)
- acs, scripts = sc.listscripts()
- return render_to_json_response(dict(
- respmsg=_("Filters set deleted"), newfs=acs
- ))
-
-
-@login_required
-@needs_mailbox()
-def activate_filters_set(request, name):
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- try:
- sc.activatescript(name)
- except SieveClientError as e:
- return ajax_response(request, "ko", respmsg=str(e))
- return ajax_response(request, respmsg=_("Filters set activated"))
-
-
-@login_required
-@needs_mailbox()
-def download_filters_set(request, name):
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- try:
- script = sc.getscript(name)
- except SieveClientError as e:
- return ajax_response(request, "ko", respmsg=str(e))
-
- resp = HttpResponse(script)
- resp["Content-Type"] = "text/plain; charset=utf-8"
- resp["Content-Length"] = len(script)
- resp["Content-Disposition"] = build_header('%s.txt' % name)
- return resp
-
-
-@login_required
-@needs_mailbox()
-def toggle_filter_state(request, setname, fname):
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- if isinstance(fname, unicode):
- fname = fname.encode("utf-8")
- fset = sc.getscript(setname, format="fset")
- if fset.is_filter_disabled(fname):
- ret = fset.enablefilter(fname)
- newstate = _("yes")
- color = "green"
- else:
- ret = fset.disablefilter(fname)
- newstate = _("no")
- color = "red"
- if not ret:
- pass
- sc.pushscript(setname, str(fset))
- return render_to_json_response({
- "label": newstate,
- "color": color
- })
-
-
-def move_filter(request, setname, fname, direction):
- sc = SieveClient(user=request.user.username,
- password=request.session["password"])
- fset = sc.getscript(setname, format="fset")
- fset.movefilter(fname.encode("utf-8"), direction)
- sc.pushscript(setname, str(fset))
- return ajax_response(
- request, template="sievefilters/guieditor.html", fs=fset
- )
-
-
-@login_required
-@needs_mailbox()
-def move_filter_up(request, setname, fname):
- return move_filter(request, setname, fname, "up")
-
-
-@login_required
-@needs_mailbox()
-def move_filter_down(request, setname, fname):
- return move_filter(request, setname, fname, "down")
From b0f88c3988249abc8e2d7e3339d618bd5da2f88b Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Feb 2015 14:48:50 +0100
Subject: [PATCH 07/25] Remove extensions.
---
modoboa/extensions/__init__.py | 0
.../extensions/postfix_autoreply/__init__.py | 0
.../postfix_autoreply/app_settings.py | 63 ------
modoboa/extensions/postfix_autoreply/forms.py | 81 -------
.../postfix_autoreply/general_callbacks.py | 151 -------------
.../postfix_autoreply/management/__init__.py | 2 -
.../management/commands/__init__.py | 2 -
.../management/commands/autoreply.py | 68 ------
.../migrations/0001_initial.py | 73 ------
.../postfix_autoreply/migrations/__init__.py | 0
.../extensions/postfix_autoreply/models.py | 43 ----
.../postfix_autoreply/modo_extension.py | 65 ------
.../postfix_autoreply/autoreply.html | 11 -
modoboa/extensions/postfix_autoreply/tests.py | 125 -----------
modoboa/extensions/postfix_autoreply/views.py | 45 ----
.../postfix_relay_domains/__init__.py | 0
.../postfix_relay_domains/amavis_callbacks.py | 35 ---
.../postfix_relay_domains/app_settings.py | 25 ---
.../postfix_relay_domains/factories.py | 25 ---
.../extensions/postfix_relay_domains/forms.py | 184 ---------------
.../general_callbacks.py | 154 -------------
.../extensions/postfix_relay_domains/lib.py | 14 --
.../postfix_relay_domains/limits_callbacks.py | 85 -------
.../migrations/0001_initial.py | 59 -----
.../migrations/__init__.py | 0
.../postfix_relay_domains/models.py | 210 ------------------
.../postfix_relay_domains/modo_extension.py | 55 -----
.../postfix_relay_domains/js/relay_domains.js | 100 ---------
.../new_relaydomain_form.html | 3 -
.../relaydomain_form.html | 7 -
.../postfix_relay_domains/service_field.html | 4 -
.../extensions/postfix_relay_domains/tests.py | 209 -----------------
.../extensions/postfix_relay_domains/urls.py | 13 --
.../extensions/postfix_relay_domains/views.py | 75 -------
34 files changed, 1986 deletions(-)
delete mode 100644 modoboa/extensions/__init__.py
delete mode 100644 modoboa/extensions/postfix_autoreply/__init__.py
delete mode 100644 modoboa/extensions/postfix_autoreply/app_settings.py
delete mode 100644 modoboa/extensions/postfix_autoreply/forms.py
delete mode 100644 modoboa/extensions/postfix_autoreply/general_callbacks.py
delete mode 100644 modoboa/extensions/postfix_autoreply/management/__init__.py
delete mode 100644 modoboa/extensions/postfix_autoreply/management/commands/__init__.py
delete mode 100644 modoboa/extensions/postfix_autoreply/management/commands/autoreply.py
delete mode 100644 modoboa/extensions/postfix_autoreply/migrations/0001_initial.py
delete mode 100644 modoboa/extensions/postfix_autoreply/migrations/__init__.py
delete mode 100644 modoboa/extensions/postfix_autoreply/models.py
delete mode 100644 modoboa/extensions/postfix_autoreply/modo_extension.py
delete mode 100644 modoboa/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html
delete mode 100644 modoboa/extensions/postfix_autoreply/tests.py
delete mode 100644 modoboa/extensions/postfix_autoreply/views.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/__init__.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/amavis_callbacks.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/app_settings.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/factories.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/forms.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/general_callbacks.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/lib.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/limits_callbacks.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/migrations/0001_initial.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/migrations/__init__.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/models.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/modo_extension.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js
delete mode 100644 modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/new_relaydomain_form.html
delete mode 100644 modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/relaydomain_form.html
delete mode 100644 modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html
delete mode 100644 modoboa/extensions/postfix_relay_domains/tests.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/urls.py
delete mode 100644 modoboa/extensions/postfix_relay_domains/views.py
diff --git a/modoboa/extensions/__init__.py b/modoboa/extensions/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/postfix_autoreply/__init__.py b/modoboa/extensions/postfix_autoreply/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/postfix_autoreply/app_settings.py b/modoboa/extensions/postfix_autoreply/app_settings.py
deleted file mode 100644
index 005f29029..000000000
--- a/modoboa/extensions/postfix_autoreply/app_settings.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# coding: utf-8
-
-"""Custom settings."""
-
-from django import forms
-from django.utils.translation import ugettext_lazy
-
-from modoboa.lib.form_utils import SeparatorField
-from modoboa.lib.parameters import AdminParametersForm
-
-
-class ParametersForm(AdminParametersForm):
- app = "postfix_autoreply"
-
- general_sep = SeparatorField(label=ugettext_lazy("General"))
-
- autoreplies_timeout = forms.IntegerField(
- label=ugettext_lazy("Automatic reply timeout"),
- initial=86400,
- help_text=ugettext_lazy(
- "Timeout in seconds between two auto-replies to the same recipient"
- ),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- default_subject = forms.CharField(
- label=ugettext_lazy("Default subject"),
- initial=ugettext_lazy("I'm off"),
- help_text=ugettext_lazy(
- "Default subject used when an auto-reply message is created "
- "automatically"
- ),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
-
- default_content = forms.CharField(
- label=ugettext_lazy("Default content"),
- initial=ugettext_lazy(
- """I'm currently off. I'll answer as soon as I come back.
-
-Best regards,
-%(name)s
-"""),
- help_text=ugettext_lazy(
- "Default content used when an auto-reply message is created "
- "automatically. The '%(name)s' macro will be replaced by the "
- "user's full name."
- ),
- widget=forms.widgets.Textarea(attrs={"class": "form-control"})
- )
-
- def clean_default_content(self):
- """Check if the provided value is valid.
-
- Must be a valid format string which will be used with the %
- operator.
- """
- tpl = self.cleaned_data["default_content"]
- try:
- test = tpl % {"name": "Antoine Nguyen"}
- except (KeyError, ValueError):
- raise forms.ValidationError(ugettext_lazy("Invalid syntax"))
- return tpl
diff --git a/modoboa/extensions/postfix_autoreply/forms.py b/modoboa/extensions/postfix_autoreply/forms.py
deleted file mode 100644
index 2252672bf..000000000
--- a/modoboa/extensions/postfix_autoreply/forms.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# coding: utf-8
-
-"""Custom forms."""
-
-from collections import OrderedDict
-
-from django import forms
-from django.utils import timezone
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from .models import ARmessage
-
-
-class ARmessageForm(forms.ModelForm):
-
- fromdate = forms.DateTimeField(
- label=ugettext_lazy('From'),
- required=False,
- help_text=ugettext_lazy("Activate your auto reply from this date"),
- widget=forms.TextInput(
- attrs={'class': 'datefield form-control', 'readonly': 'readonly'}
- )
- )
- untildate = forms.DateTimeField(
- label=ugettext_lazy('Until'),
- required=False,
- help_text=ugettext_lazy("Activate your auto reply until this date"),
- widget=forms.TextInput(
- attrs={'class': 'datefield form-control', 'readonly': 'readonly'}
- )
- )
- subject = forms.CharField(
- widget=forms.TextInput(
- attrs={'class': 'form-control'}
- )
- )
- content = forms.CharField(
- widget=forms.Textarea(
- attrs={'class': 'form-control'}
- )
- )
-
- class Meta:
- model = ARmessage
- fields = ('subject', 'content', 'enabled')
-
- def __init__(self, *args, **kwargs):
- super(ARmessageForm, self).__init__(*args, **kwargs)
- self.fields = OrderedDict(
- (key, self.fields[key]) for key in
- ['subject', 'content', 'fromdate', 'untildate', 'enabled']
- )
- if 'instance' in kwargs and kwargs['instance'] is not None:
- self.fields['fromdate'].initial = \
- kwargs['instance'].fromdate.replace(second=0, microsecond=0)
- self.fields['untildate'].initial = kwargs['instance'].untildate
-
- def clean(self):
- """Custom fields validaton.
-
- We want to be sure that fromdate < untildate and that they are
- both in the future ONLY IF the autoreply is beeing activated.
-
- """
- super(ARmessageForm, self).clean()
- if not self.cleaned_data["enabled"]:
- return self.cleaned_data
- if self.cleaned_data["fromdate"] is not None:
- if self.cleaned_data["fromdate"] < timezone.now():
- self.add_error("fromdate", _("This date is over"))
- else:
- self.cleaned_data['fromdate'] = timezone.now()
- if self.cleaned_data["untildate"] is not None:
- untildate = self.cleaned_data["untildate"]
- if untildate < timezone.now():
- self.add_error("untildate", _("This date is over"))
- elif "fromdate" in self.cleaned_data and \
- untildate < self.cleaned_data["fromdate"]:
- self.add_error(
- "untildate", _("Must be greater than start date"))
- return self.cleaned_data
diff --git a/modoboa/extensions/postfix_autoreply/general_callbacks.py b/modoboa/extensions/postfix_autoreply/general_callbacks.py
deleted file mode 100644
index 450cf0b42..000000000
--- a/modoboa/extensions/postfix_autoreply/general_callbacks.py
+++ /dev/null
@@ -1,151 +0,0 @@
-"""Event callbacks."""
-
-from django.utils import timezone
-from django.utils.translation import ugettext_lazy
-
-from .models import ARmessage
-from modoboa.extensions.postfix_autoreply.models import Transport, Alias
-from modoboa.lib import events, parameters
-
-
-@events.observe("ExtraUprefsJS")
-def extra_js(user):
- return ["""function autoreply_cb() {
- $('.datefield').datetimepicker({
- format: 'YYYY-MM-DD hh:mm:ss',
- language: '%(lang)s'
- });
-}
-""" % {'lang': parameters.get_user(user, "LANG", app="core")}
- ]
-
-
-@events.observe("UserMenuDisplay")
-def menu(target, user):
- if target != "uprefs_menu":
- return []
- if not user.mailbox_set.count():
- return []
- return [
- {"name": "autoreply",
- "class": "ajaxnav",
- "url": "autoreply/",
- "label": ugettext_lazy("Auto-reply message")}
- ]
-
-
-@events.observe("DomainCreated")
-def onDomainCreated(user, domain):
- transport = Transport()
- transport.domain = "autoreply.%s" % domain.name
- transport.method = "autoreply:"
- transport.save()
-
-
-@events.observe("DomainModified")
-def onDomainModified(domain):
- if domain.oldname == domain.name:
- return
- Transport.objects.filter(domain="autoreply.%s" % domain.oldname) \
- .update(domain="autoreply.%s" % domain.name)
- for al in Alias.objects.filter(
- full_address__contains="@%s" % domain.oldname):
- new_address = al.full_address.replace(
- "@%s" % domain.oldname,
- "@%s" % domain.name)
- al.full_address = new_address
- al.autoreply_address = "%s@autoreply.%s" % (new_address, domain.name)
- al.save()
-
-
-@events.observe("DomainDeleted")
-def onDomainDeleted(domain):
- Transport.objects.filter(domain="autoreply.%s" % domain.name).delete()
-
-
-@events.observe("MailboxCreated")
-def onMailboxCreated(user, mailbox):
- alias = Alias()
- alias.full_address = mailbox.full_address
- alias.autoreply_address = \
- "%s@autoreply.%s" % (mailbox.full_address, mailbox.domain.name)
- alias.save()
-
-
-@events.observe("MailboxDeleted")
-def onMailboxDeleted(mailboxes):
- from modoboa.extensions.admin.models import Mailbox
-
- if isinstance(mailboxes, Mailbox):
- mailboxes = [mailboxes]
- for mailbox in mailboxes:
- try:
- alias = Alias.objects.get(full_address=mailbox.full_address)
- except Alias.DoesNotExist:
- pass
- else:
- alias.delete()
-
-
-@events.observe("MailboxModified")
-def onMailboxModified(mailbox):
- if not hasattr(mailbox, 'old_full_address'):
- return
- if mailbox.full_address == mailbox.old_full_address:
- return
- alias = Alias.objects.get(full_address=mailbox.old_full_address)
- alias.full_address = mailbox.full_address
- alias.autoreply_address = \
- "%s@autoreply.%s" % (mailbox.full_address, mailbox.domain.name)
- alias.save()
-
-
-@events.observe("ExtraFormFields")
-def extra_mailform_fields(form_name, mailbox=None):
- """Define extra fields to include in mail forms.
-
- For now, only the auto-reply state can be modified.
-
- :param str form_name: form name (must be 'mailform')
- :param Mailbox mailbox: mailbox
- """
- from modoboa.lib.form_utils import YesNoField
-
- if form_name != "mailform":
- return []
- status = False
- if mailbox is not None and mailbox.armessage_set.count():
- status = mailbox.armessage_set.all()[0].enabled
- return [
- ('autoreply', YesNoField(
- label=ugettext_lazy("Enable auto-reply"),
- initial="yes" if status else "no",
- required=False,
- help_text=ugettext_lazy("Enable or disable Postfix auto-reply")
- ))
- ]
-
-
-@events.observe("SaveExtraFormFields")
-def save_extra_mailform_fields(form_name, mailbox, values):
- """Set the auto-reply status for a mailbox.
-
- If a corresponding auto-reply message exists, we update its
- status. Otherwise, we create a message using default values.
-
- :param str form_name: form name (must be 'mailform')
- :param Mailbox mailbox: mailbox
- :param dict values: form values
- """
- if form_name != 'mailform':
- return
- if mailbox.armessage_set.count():
- arm = mailbox.armessage_set.all()[0]
- else:
- arm = ARmessage(mbox=mailbox)
- arm.subject = parameters.get_admin("DEFAULT_SUBJECT")
- arm.content = parameters.get_admin("DEFAULT_CONTENT") \
- % {'name': mailbox.user.fullname}
- arm.fromdate = timezone.now()
- arm.enabled = True if values['autoreply'] == 'yes' else False
- arm.save()
diff --git a/modoboa/extensions/postfix_autoreply/management/__init__.py b/modoboa/extensions/postfix_autoreply/management/__init__.py
deleted file mode 100644
index 394a0a067..000000000
--- a/modoboa/extensions/postfix_autoreply/management/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
diff --git a/modoboa/extensions/postfix_autoreply/management/commands/__init__.py b/modoboa/extensions/postfix_autoreply/management/commands/__init__.py
deleted file mode 100644
index 394a0a067..000000000
--- a/modoboa/extensions/postfix_autoreply/management/commands/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
diff --git a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py
deleted file mode 100644
index 09482185c..000000000
--- a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-import sys
-import datetime
-
-from django.core.management.base import BaseCommand, CommandError
-from django.utils import timezone
-
-from modoboa.core.management.commands import CloseConnectionMixin
-from modoboa.lib import parameters
-from modoboa.lib.email_utils import split_mailbox, sendmail_simple
-from modoboa.extensions.admin.models import Mailbox
-from modoboa.extensions.postfix_autoreply.models import ARmessage, ARhistoric
-
-
-def send_autoreply(sender, mailbox, armessage):
- if armessage.fromdate > timezone.now():
- return
- if armessage.untildate is not None \
- and armessage.untildate < timezone.now():
- armessage.enabled = False
- armessage.save()
- return
-
- try:
- lastar = ARhistoric.objects.get(armessage=armessage.id, sender=sender)
- timeout = parameters.get_admin("AUTOREPLIES_TIMEOUT",
- app="postfix_autoreply")
- delta = datetime.timedelta(seconds=int(timeout))
- now = timezone.make_aware(datetime.datetime.now(),
- timezone.get_default_timezone())
- if lastar.last_sent + delta > now:
- sys.exit(0)
- except ARhistoric.DoesNotExist:
- lastar = ARhistoric()
- lastar.armessage = armessage
- lastar.sender = sender
-
- sendmail_simple(mailbox.user.encoded_address, sender, armessage.subject,
- armessage.content.encode('utf-8'))
-
- lastar.last_sent = datetime.datetime.now()
- lastar.save()
-
-
-class Command(BaseCommand, CloseConnectionMixin):
- args = ' '
- help = 'Send autoreply emails'
-
- def handle(self, *args, **options):
- if len(args) < 2:
- raise CommandError(
- "usage: ./manage.py autoreply ")
-
- sender = args[0]
- for fulladdress in args[1:]:
- address, domain = split_mailbox(fulladdress)
- try:
- mbox = Mailbox.objects.get(address=address, domain__name=domain)
- except Mailbox.DoesNotExist:
- print "Unknown recipient %s" % (fulladdress)
- continue
- try:
- armessage = ARmessage.objects.get(mbox=mbox.id, enabled=True)
- except ARmessage.DoesNotExist:
- continue
-
- send_autoreply(sender, mbox, armessage)
diff --git a/modoboa/extensions/postfix_autoreply/migrations/0001_initial.py b/modoboa/extensions/postfix_autoreply/migrations/0001_initial.py
deleted file mode 100644
index 4bb61e930..000000000
--- a/modoboa/extensions/postfix_autoreply/migrations/0001_initial.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-import django.utils.timezone
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('admin', '__first__'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Alias',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('full_address', models.CharField(max_length=255)),
- ('autoreply_address', models.CharField(max_length=255)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='ARhistoric',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('last_sent', models.DateTimeField(auto_now=True)),
- ('sender', models.CharField(max_length=254)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='ARmessage',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('subject', models.CharField(help_text='The subject that will appear in sent emails', max_length=255, verbose_name='subject')),
- ('content', models.TextField(help_text='The content that will appear in sent emails', verbose_name='content')),
- ('enabled', models.BooleanField(default=False, help_text='Activate/Deactivate your auto reply', verbose_name='enabled')),
- ('fromdate', models.DateTimeField(default=django.utils.timezone.now)),
- ('untildate', models.DateTimeField(null=True, blank=True)),
- ('mbox', models.ForeignKey(to='admin.Mailbox')),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Transport',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('domain', models.CharField(max_length=300)),
- ('method', models.CharField(max_length=255)),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.AddField(
- model_name='arhistoric',
- name='armessage',
- field=models.ForeignKey(to='postfix_autoreply.ARmessage'),
- preserve_default=True,
- ),
- migrations.AlterUniqueTogether(
- name='arhistoric',
- unique_together=set([('armessage', 'sender')]),
- ),
- ]
diff --git a/modoboa/extensions/postfix_autoreply/migrations/__init__.py b/modoboa/extensions/postfix_autoreply/migrations/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/postfix_autoreply/models.py b/modoboa/extensions/postfix_autoreply/models.py
deleted file mode 100644
index 0c53a163b..000000000
--- a/modoboa/extensions/postfix_autoreply/models.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from django.utils import timezone
-
-from modoboa.extensions.admin.models import Mailbox
-
-
-class Transport(models.Model):
- domain = models.CharField(max_length=300)
- method = models.CharField(max_length=255)
-
-
-class Alias(models.Model):
- full_address = models.CharField(max_length=255)
- autoreply_address = models.CharField(max_length=255)
-
-
-class ARmessage(models.Model):
- mbox = models.ForeignKey(Mailbox)
- subject = models.CharField(
- _('subject'), max_length=255,
- help_text=_("The subject that will appear in sent emails")
- )
- content = models.TextField(
- _('content'),
- help_text=_("The content that will appear in sent emails")
- )
- enabled = models.BooleanField(
- _('enabled'),
- help_text=_("Activate/Deactivate your auto reply"),
- default=False
- )
- fromdate = models.DateTimeField(default=timezone.now)
- untildate = models.DateTimeField(null=True, blank=True)
-
-
-class ARhistoric(models.Model):
- armessage = models.ForeignKey(ARmessage)
- last_sent = models.DateTimeField(auto_now=True)
- sender = models.CharField(max_length=254)
-
- class Meta:
- unique_together = ("armessage", "sender")
diff --git a/modoboa/extensions/postfix_autoreply/modo_extension.py b/modoboa/extensions/postfix_autoreply/modo_extension.py
deleted file mode 100644
index 90e861cde..000000000
--- a/modoboa/extensions/postfix_autoreply/modo_extension.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# coding: utf-8
-"""
-Postfix auto-replies plugin.
-
-This module provides a way to integrate Modoboa auto-reply
-functionality into Postfix.
-
-"""
-
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.extensions.admin.models import Domain
-from modoboa.lib import events, parameters
-from . import general_callbacks
-from .models import Transport, Alias
-
-
-class PostfixAutoreply(ModoExtension):
-
- """
- Auto-reply (vacation) functionality using Postfix.
-
- """
- name = "postfix_autoreply"
- label = "Postfix autoreply"
- version = "1.0"
- description = ugettext_lazy(
- "Auto-reply (vacation) functionality using Postfix")
-
- def load(self):
- from modoboa.extensions.postfix_autoreply.app_settings import (
- ParametersForm
- )
- parameters.register(
- ParametersForm, ugettext_lazy("Automatic replies"))
-
- def load_initial_data(self):
- """Create records for existing domains."""
- for dom in Domain.objects.all():
- try:
- Transport.objects.get(domain="autoreply.%s" % dom.name)
- except Transport.DoesNotExist:
- general_callbacks.onDomainCreated(None, dom)
- else:
- continue
-
- for mb in dom.mailbox_set.all():
- try:
- Alias.objects.get(full_address=mb.full_address)
- except Alias.DoesNotExist:
- general_callbacks.onMailboxCreated(None, mb)
-
-exts_pool.register_extension(PostfixAutoreply)
-
-
-@events.observe("ExtraUprefsRoutes")
-def extra_routes():
- from django.conf.urls import url
-
- return [
- url(r'^user/autoreply/$',
- 'modoboa.extensions.postfix_autoreply.views.autoreply',
- name="autoreply")
- ]
diff --git a/modoboa/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html b/modoboa/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html
deleted file mode 100644
index f30ca8166..000000000
--- a/modoboa/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% load i18n form_tags %}{% load url from future %}
-{% trans "Auto-reply message" %} {% trans "Define a message to automatically send when you are off" %}
-
-{% csrf_token %}
- {% render_form form %}
-
- {% trans 'Update' %}
-
-
diff --git a/modoboa/extensions/postfix_autoreply/tests.py b/modoboa/extensions/postfix_autoreply/tests.py
deleted file mode 100644
index 3e1dd172e..000000000
--- a/modoboa/extensions/postfix_autoreply/tests.py
+++ /dev/null
@@ -1,125 +0,0 @@
-from django.core.urlresolvers import reverse
-from modoboa.core.models import User
-from modoboa.lib.tests import ModoTestCase
-from modoboa.extensions.admin import factories
-from modoboa.extensions.admin.models import (
- Domain
-)
-from modoboa.extensions.postfix_autoreply.models import (
- Transport, Alias, ARmessage
-)
-
-
-class EventsTestCase(ModoTestCase):
- fixtures = ['initial_users.json']
-
- def setUp(self):
- super(EventsTestCase, self).setUp()
- factories.populate_database()
-
- def test_domain_created_event(self):
- values = {
- "name": "domain.tld", "quota": 100, "create_dom_admin": "no",
- "stepid": 'step2'
- }
- self.ajax_post(
- reverse("admin:domain_add"), values
- )
- trans = Transport.objects.get(domain='autoreply.domain.tld')
-
- def test_domain_deleted_event(self):
- dom = Domain.objects.get(name="test.com")
- trans = Transport.objects.get(domain='autoreply.test.com')
- self.ajax_post(
- reverse("admin:domain_delete", args=[dom.id]),
- {}
- )
- with self.assertRaises(Transport.DoesNotExist):
- Transport.objects.get(domain='autoreply.test.com')
-
- def test_domain_modified_event(self):
- values = {
- "name": "test.fr", "quota": 100, "enabled": True
- }
- dom = Domain.objects.get(name="test.com")
- self.ajax_post(
- reverse("admin:domain_change", args=[dom.id]),
- values
- )
- trans = Transport.objects.get(domain='autoreply.test.fr')
- self.assertEqual(
- Alias.objects.filter(full_address__contains='@test.fr').count(), 2
- )
- for al in Alias.objects.filter(full_address__contains='@test.fr'):
- self.assertIn('autoreply.test.fr', al.autoreply_address)
-
- def test_mailbox_created_event(self):
- values = {
- 'username': "tester@test.com",
- 'first_name': 'Tester', 'last_name': 'Toto',
- 'password1': 'toto', 'password2': 'toto', 'role': 'SimpleUsers',
- 'quota_act': True, 'is_active': True, 'email': 'tester@test.com',
- 'stepid': 'step2', 'autoreply': 'no'
- }
- self.ajax_post(
- reverse("admin:account_add"), values
- )
- al = Alias.objects.get(full_address='tester@test.com')
- self.assertEqual(
- al.autoreply_address, 'tester@test.com@autoreply.test.com')
- arm = ARmessage.objects.get(mbox__address='tester')
-
- def test_mailbox_deleted_event(self):
- account = User.objects.get(username="user@test.com")
- self.ajax_post(
- reverse("admin:account_delete", args=[account.id]),
- {}
- )
- with self.assertRaises(Alias.DoesNotExist):
- Alias.objects.get(full_address='user@test.com')
- with self.assertRaises(ARmessage.DoesNotExist):
- ARmessage.objects.get(
- mbox__address='user', mbox__domain__name='test.com')
-
- def test_modify_mailbox_event(self):
- values = {
- 'username': "leon@test.com",
- 'first_name': 'Tester', 'last_name': 'Toto',
- 'role': 'SimpleUsers', 'quota_act': True,
- 'is_active': True, 'email': 'leon@test.com',
- 'autoreply': 'no'
- }
- account = User.objects.get(username="user@test.com")
- self.ajax_post(
- reverse("admin:account_change", args=[account.id]),
- values
- )
- with self.assertRaises(Alias.DoesNotExist):
- Alias.objects.get(full_address='user@test.com')
- al = Alias.objects.get(full_address='leon@test.com')
-
-
-class FormTestCase(ModoTestCase):
- fixtures = ['initial_users.json']
-
- def setUp(self):
- super(FormTestCase, self).setUp()
- factories.populate_database()
-
- # def test_set_autoreply(self):
- # self.clt.get(
- # reverse('modoboa.core.views.user.index')
- # )
- # values = {
- # 'subject': 'test', 'content': "I'm off", "enabled": True
- # }
- # self.ajax_post(
- # reverse('modoboa.extensions.postfix_autoreply.views.autoreply'),
- # values
- # )
- # account = User.objects.get(username="user@test.com")
- # arm = ARmessage.objects.get(mbox=account.mailbox_set.all()[0])
- # self.assertEqual(arm.subject, 'test')
- # self.assertTrue(arm.enabled)
- # self.assertFalse(arm.untildate)
- # self.assertTrue(arm.fromdate)
diff --git a/modoboa/extensions/postfix_autoreply/views.py b/modoboa/extensions/postfix_autoreply/views.py
deleted file mode 100644
index cbf7befe0..000000000
--- a/modoboa/extensions/postfix_autoreply/views.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# coding: utf-8
-from datetime import date
-from django.contrib.auth.decorators import login_required
-from django.utils.translation import ugettext as _
-from modoboa.lib.web_utils import (
- render_to_json_response, _render_to_string
-)
-from modoboa.extensions.admin.lib import needs_mailbox
-from modoboa.extensions.admin.models import Mailbox
-from .forms import ARmessageForm
-from .models import ARmessage
-
-
-@login_required
-@needs_mailbox()
-def autoreply(request, tplname="postfix_autoreply/autoreply.html"):
- mb = Mailbox.objects.get(user=request.user.id)
- try:
- arm = ARmessage.objects.get(mbox=mb.id)
- except ARmessage.DoesNotExist:
- arm = None
- if request.method == "POST":
- if arm:
- form = ARmessageForm(request.POST, instance=arm)
- else:
- form = ARmessageForm(request.POST)
- if form.is_valid():
- arm = form.save(commit=False)
- arm.fromdate = form.cleaned_data["fromdate"]
- arm.untildate = form.cleaned_data["untildate"]
- arm.mbox = mb
- arm.save()
- return render_to_json_response(
- _("Auto reply message updated successfully.")
- )
-
- return render_to_json_response(
- {"form_errors": form.errors}, status=400
- )
-
- form = ARmessageForm(instance=arm)
- return render_to_json_response({
- "content": _render_to_string(request, tplname, {"form": form}),
- "onload_cb": "autoreply_cb"
- })
diff --git a/modoboa/extensions/postfix_relay_domains/__init__.py b/modoboa/extensions/postfix_relay_domains/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/postfix_relay_domains/amavis_callbacks.py b/modoboa/extensions/postfix_relay_domains/amavis_callbacks.py
deleted file mode 100644
index d73770986..000000000
--- a/modoboa/extensions/postfix_relay_domains/amavis_callbacks.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from modoboa.lib import events
-from modoboa.extensions.amavis.lib import (
- create_user_and_policy, update_user_and_policy, delete_user_and_policy,
- create_user_and_use_policy, delete_user
-)
-
-
-@events.observe("RelayDomainCreated")
-def on_relay_domain_created(user, rdomain):
- create_user_and_policy("@{0}".format(rdomain.name))
-
-
-@events.observe("RelayDomainModified")
-def on_relay_domain_modified(rdomain):
- update_user_and_policy(
- "@{0}".format(rdomain.oldname), "@{0}".format(rdomain.name)
- )
-
-
-@events.observe("RelayDomainDeleted")
-def on_relay_domain_deleted(rdomain):
- delete_user_and_policy("@{0}".format(rdomain.name))
-
-
-@events.observe("RelayDomainAliasCreated")
-def on_relay_domain_alias_created(user, rdomainalias):
- create_user_and_use_policy(
- "@{0}".format(rdomainalias.name),
- "@{0}".format(rdomainalias.target.name)
- )
-
-
-@events.observe("RelayDomainAliasDeleted")
-def on_relay_domain_alias_deleted(rdomainalias):
- delete_user("@{0}".format(rdomainalias.name))
diff --git a/modoboa/extensions/postfix_relay_domains/app_settings.py b/modoboa/extensions/postfix_relay_domains/app_settings.py
deleted file mode 100644
index 80cfc6a4d..000000000
--- a/modoboa/extensions/postfix_relay_domains/app_settings.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""
-Relay domains settings definition.
-"""
-
-from django import forms
-from django.utils.translation import ugettext_lazy
-
-from modoboa.lib import parameters
-from modoboa.lib.form_utils import SeparatorField
-
-
-class AdminParametersForm(parameters.AdminParametersForm):
-
- """Admin parameters definition."""
-
- app = "postfix_relay_domains"
-
- general_sep = SeparatorField(label=ugettext_lazy("General"))
-
- master_cf_path = forms.CharField(
- label=ugettext_lazy("Postfix's master.cf path"),
- initial="/etc/postfix/master.cf",
- help_text=ugettext_lazy('Path to the master.cf configuration file'),
- widget=forms.TextInput(attrs={"class": "form-control"})
- )
diff --git a/modoboa/extensions/postfix_relay_domains/factories.py b/modoboa/extensions/postfix_relay_domains/factories.py
deleted file mode 100644
index 1a0c0a5a2..000000000
--- a/modoboa/extensions/postfix_relay_domains/factories.py
+++ /dev/null
@@ -1,25 +0,0 @@
-import factory
-from modoboa.core.factories import PermissionFactory
-from . import models
-
-
-class ServiceFactory(factory.DjangoModelFactory):
- FACTORY_FOR = models.Service
- FACTORY_DJANGO_GET_OR_CREATE = ('name', )
-
- name = 'dummy'
-
-
-class RelayDomainFactory(PermissionFactory):
- FACTORY_FOR = models.RelayDomain
-
- target_host = 'external.host.tld'
- enabled = True
- verify_recipients = True
- service = factory.SubFactory(ServiceFactory)
-
-
-class RelayDomainAliasFactory(PermissionFactory):
- FACTORY_FOR = models.RelayDomainAlias
-
- enabled = True
diff --git a/modoboa/extensions/postfix_relay_domains/forms.py b/modoboa/extensions/postfix_relay_domains/forms.py
deleted file mode 100644
index ddafe295d..000000000
--- a/modoboa/extensions/postfix_relay_domains/forms.py
+++ /dev/null
@@ -1,184 +0,0 @@
-"""
-Postfix relay domains extension forms.
-"""
-from django import forms
-from django.core.urlresolvers import reverse
-from django.http import QueryDict
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-from .models import RelayDomain, RelayDomainAlias
-from modoboa.extensions.admin.models import Domain, DomainAlias
-from modoboa.lib import events
-from modoboa.lib.form_utils import DynamicForm, DomainNameField, TabForms
-from modoboa.lib.web_utils import render_to_json_response
-
-
-class RelayDomainFormGeneral(forms.ModelForm, DynamicForm):
- aliases = DomainNameField(
- label=ugettext_lazy("Alias(es)"),
- required=False,
- help_text=ugettext_lazy(
- "Alias(es) of this relay domain. Indicate only one name per input"
- ", press ENTER to add a new input."
- )
- )
-
- class Meta:
- model = RelayDomain
- exclude = ['dates']
- widgets = {
- "service": forms.Select(attrs={"class": "form-control"})
- }
-
- def __init__(self, *args, **kwargs):
- self.oldname = None
- if "instance" in kwargs:
- self.oldname = kwargs["instance"].name
- super(RelayDomainFormGeneral, self).__init__(*args, **kwargs)
- self.field_widths = {
- "service": 3
- }
- if args and isinstance(args[0], QueryDict):
- self._load_from_qdict(args[0], "aliases", DomainNameField)
- elif 'instance' in kwargs:
- rd = kwargs['instance']
- for pos, rdalias in enumerate(rd.relaydomainalias_set.all()):
- name = "aliases_%d" % (pos + 1)
- self._create_field(forms.CharField, name, rdalias.name, 3)
-
- def clean(self):
- """Custom fields validaton.
-
- We want to prevent duplicate names between domains, relay
- domains, domain aliases and relay domain aliases.
-
- The validation way is not very smart...
- """
- super(RelayDomainFormGeneral, self).clean()
- cleaned_data = self.cleaned_data
- for dtype, label in [(Domain, _('domain')),
- (DomainAlias, _('domain alias')),
- (RelayDomainAlias, _('relay domain alias'))]:
- try:
- dtype.objects.get(name=cleaned_data['name'])
- except dtype.DoesNotExist:
- pass
- else:
- self.add_error(
- "name", _("A %s with this name already exists") % label
- )
- break
-
- for k in cleaned_data.keys():
- if not k.startswith("aliases"):
- continue
- if not cleaned_data[k]:
- del cleaned_data[k]
- continue
- for dtype, name in [(RelayDomain, _('relay domain')),
- (DomainAlias, _('domain alias')),
- (Domain, _('domain'))]:
- try:
- dtype.objects.get(name=cleaned_data[k])
- except dtype.DoesNotExist:
- pass
- else:
- self.add_error(
- k, _("A %s with this name already exists") % name)
- break
-
- return cleaned_data
-
- def save(self, user, commit=True, rdomalias_post_create=False):
- """Custom save method.
-
- As relay domain aliases are defined using the same form as
- relay domains, we need to save them manually.
-
- :param ``User`` user: connected user
- """
- rd = super(RelayDomainFormGeneral, self).save(commit=False)
- if commit:
- rd.oldname = self.oldname
- rd.save()
- aliases = []
- for k, v in self.cleaned_data.iteritems():
- if not k.startswith("aliases"):
- continue
- if v in ["", None]:
- continue
- aliases.append(v)
- for rdalias in rd.relaydomainalias_set.all():
- if rdalias.name not in aliases:
- rdalias.delete()
- else:
- aliases.remove(rdalias.name)
- if aliases:
- events.raiseEvent(
- "CanCreate", user, "relay_domain_aliases", len(aliases)
- )
- for alias in aliases:
- try:
- rd.relaydomainalias_set.get(name=alias)
- except RelayDomainAlias.DoesNotExist:
- pass
- else:
- continue
- al = RelayDomainAlias(
- name=alias, target=rd, enabled=rd.enabled
- )
- al.save(creator=user) \
- if rdomalias_post_create else al.save()
- return rd
-
-
-class RelayDomainForm(TabForms):
-
- """Specific edition form for relay domains.
-
- We use a *tabs* compatible form because extensions can add their
- own tab. (ex: amavis)
- """
-
- def __init__(self, request, *args, **kwargs):
- self.user = request.user
- self.forms = []
- if self.user.has_perm("postfix_relay_domains.change_relaydomain"):
- self.forms.append({
- 'id': 'general', 'title': _("General"),
- 'formtpl': 'postfix_relay_domains/relaydomain_form.html',
- 'cls': RelayDomainFormGeneral, 'mandatory': True
- })
-
- cbargs = [self.user]
- if "instances" in kwargs:
- cbargs += [kwargs["instances"]["general"]]
- self.forms += events.raiseQueryEvent("ExtraRelayDomainForm", *cbargs)
- super(RelayDomainForm, self).__init__(request, *args, **kwargs)
-
- def extra_context(self, context):
- """Additional content.
- """
- rdom = self.instances["general"]
- context.update({
- 'action': reverse(
- "postfix_relay_domains:relaydomain_change", args=[rdom.id]),
- 'formid': 'rdomform',
- 'title': rdom.name
- })
-
- def save(self):
- """Custom save method
-
- As forms interact with each other, it is easier to make custom
- code to save them.
- """
- self.forms[0]['instance'].save(
- self.request.user, rdomalias_post_create=True
- )
- for f in self.forms[1:]:
- f["instance"].save(self.request.user)
-
- def done(self):
- events.raiseEvent('RelayDomainModified', self.instances["general"])
- return render_to_json_response(_('Relay domain modified'))
diff --git a/modoboa/extensions/postfix_relay_domains/general_callbacks.py b/modoboa/extensions/postfix_relay_domains/general_callbacks.py
deleted file mode 100644
index 2dd319956..000000000
--- a/modoboa/extensions/postfix_relay_domains/general_callbacks.py
+++ /dev/null
@@ -1,154 +0,0 @@
-"""General event callbacks."""
-
-from django.conf import settings
-from django.core.urlresolvers import reverse
-from django.db.models import Q
-from django.template import Template, Context
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import exts_pool
-from modoboa.lib import events
-from .models import RelayDomain, RelayDomainAlias
-
-PERMISSIONS = {
- "Resellers": [
- ("postfix_relay_domains", "relaydomain", "add_relaydomain"),
- ("postfix_relay_domains", "relaydomain", "change_relaydomain"),
- ("postfix_relay_domains", "relaydomain", "delete_relaydomain"),
- ("postfix_relay_domains", "relaydomainalias", "add_relaydomainalias"),
- ("postfix_relay_domains", "relaydomainalias",
- "change_relaydomainalias"),
- ("postfix_relay_domains", "relaydomainalias",
- "delete_relaydomainalias"),
- ("postfix_relay_domains", "service", "add_service"),
- ("postfix_relay_domains", "service", "change_service"),
- ("postfix_relay_domains", "service", "delete_service")
- ]
-}
-
-
-@events.observe("GetExtraRolePermissions")
-def extra_permissions(rolename):
- """Return extra permissions for Resellers."""
- if not exts_pool.is_extension_installed("modoboa.extensions.limits"):
- return []
- return PERMISSIONS.get(rolename, [])
-
-
-@events.observe('GetStaticContent')
-def static_content(caller, st_type, user):
- if caller != 'domains' or st_type != 'js':
- return []
-
- t = Template("""
-
-""")
- return [t.render(Context({'STATIC_URL': settings.STATIC_URL}))]
-
-
-@events.observe('ExtraDomainFilters')
-def extra_domain_filters():
- return ['srvfilter']
-
-
-@events.observe('ExtraDomainMenuEntries')
-def extra_domain_menu_entries(user):
- return [{
- "name": "newrelaydomain",
- "label": ugettext_lazy("Add relay domain"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "rdomain.domainform_cb",
- "url": reverse("postfix_relay_domains:relaydomain_add")
- }]
-
-
-@events.observe('ExtraDomainEntries')
-def extra_domain_entries(user, domfilter, searchquery, **extrafilters):
- if domfilter is not None and domfilter and domfilter != 'relaydomain':
- return []
- relay_domains = RelayDomain.objects.get_for_admin(user)
- if searchquery is not None:
- q = Q(name__contains=searchquery)
- q |= Q(relaydomainalias__name__contains=searchquery)
- relay_domains = relay_domains.filter(q).distinct()
- if 'srvfilter' in extrafilters and extrafilters['srvfilter']:
- relay_domains = relay_domains.filter(
- Q(service__name=extrafilters['srvfilter'])
- )
- return relay_domains
-
-
-@events.observe('GetDomainModifyLink')
-def rdomain_modify_link(domain):
- if not isinstance(domain, RelayDomain):
- return {}
- return {
- 'url': reverse(
- "postfix_relay_domains:relaydomain_change",
- args=[domain.id]
- ),
- 'modalcb': 'rdomain.editdomain_form_cb'
- }
-
-
-@events.observe('GetDomainActions')
-def rdomain_actions(user, domain):
- if not isinstance(domain, RelayDomain):
- return []
- if not user.has_perm("postfix_relay_domains.delete_relaydomain"):
- return []
- return [{
- "name": "delrelaydomain",
- "url": reverse(
- "postfix_relay_domains:relaydomain_delete",
- args=[domain.id]
- ),
- "title": ugettext_lazy("Delete %s?" % domain.name),
- "img": "fa fa-trash"
- }]
-
-
-@events.observe('CheckDomainName')
-def check_domain_name():
- return [
- (RelayDomain, ugettext_lazy('relay domain')),
- (RelayDomainAlias, ugettext_lazy('relay domain alias'))
- ]
-
-
-@events.observe('GetExtraLimitTemplates')
-def extra_limit_templates():
- return [
- ('relay_domains_limit', ugettext_lazy('Relay domains'),
- ugettext_lazy('Maximum number of relay domains this user can create'),
- 'Resellers'),
- ("relay_domain_aliases_limit", ugettext_lazy("Relay domain aliases"),
- ugettext_lazy(
- 'Maximum number of relay domain aliases this user can create'),
- 'Resellers'),
- ]
-
-
-@events.observe('ExtraDomainImportHelp')
-def extra_domain_import_help():
- return [ugettext_lazy("""
-relaydomain; name; target host; service; enabled; verify recipients
-relaydomainalias; name; target; enabled
-""")]
-
-
-@events.observe('ImportObject')
-def get_import_func(objtype):
- from .lib import import_relaydomain, import_relaydomainalias
-
- if objtype == 'relaydomain':
- return [import_relaydomain]
- if objtype == 'relaydomainalias':
- return [import_relaydomainalias]
- return []
diff --git a/modoboa/extensions/postfix_relay_domains/lib.py b/modoboa/extensions/postfix_relay_domains/lib.py
deleted file mode 100644
index a5c4764ec..000000000
--- a/modoboa/extensions/postfix_relay_domains/lib.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from django.db import transaction
-from .models import RelayDomain, RelayDomainAlias
-
-
-@transaction.commit_on_success
-def import_relaydomain(user, row, formopts):
- """Specific code for relay domains import"""
- RelayDomain().from_csv(user, row)
-
-
-@transaction.commit_on_success
-def import_relaydomainalias(user, row, formopts):
- """Specific code for relay domain aliases import"""
- RelayDomainAlias().from_csv(user, row)
diff --git a/modoboa/extensions/postfix_relay_domains/limits_callbacks.py b/modoboa/extensions/postfix_relay_domains/limits_callbacks.py
deleted file mode 100644
index 7a7b362cf..000000000
--- a/modoboa/extensions/postfix_relay_domains/limits_callbacks.py
+++ /dev/null
@@ -1,85 +0,0 @@
-"""Callbacks related to limits extension."""
-
-from django.utils.translation import ugettext_lazy
-
-from modoboa.extensions.limits.lib import inc_limit_usage, dec_limit_usage
-from modoboa.extensions.limits.models import LimitsPool, Limit
-from modoboa.lib import events
-from modoboa.lib.permissions import get_object_owner
-from .models import RelayDomainAlias
-
-
-def create_new_limits():
- """Create relay domains limits."""
-
- new_limits = ["relay_domains_limit", "relay_domain_aliases_limit"]
- for pool in LimitsPool.objects.all():
- for lname in new_limits:
- Limit.objects.get_or_create(name=lname, pool=pool, maxvalue=0)
-
-
-@events.observe("InitialDataLoaded")
-def load_limits_dependant_data(name):
- """Complete existing pools with new limits."""
- if name != "limits":
- return
- create_new_limits()
-
-
-@events.observe('GetExtraParameters')
-def extra_parameters(app, level):
- from django import forms
-
- if app != 'limits' or level != 'A':
- return {}
- return {
- 'deflt_relay_domains_limit': forms.IntegerField(
- label=ugettext_lazy("Relay domains"),
- initial=0,
- help_text=ugettext_lazy(
- "Maximum number of allowed relay domains for a new "
- "administrator"
- ),
- widget=forms.widgets.TextInput(
- attrs={
- "class": "col-md-1 form-control"})
- ),
- 'deflt_relay_domain_aliases_limit': forms.IntegerField(
- label=ugettext_lazy("Relay domain aliases"),
- initial=0,
- help_text=ugettext_lazy(
- "Maximum number of allowed relay domain aliases for a new "
- "administrator"
- ),
- widget=forms.widgets.TextInput(
- attrs={
- "class": "col-md-1 form-control"})
- )
- }
-
-
-@events.observe('RelayDomainCreated')
-def inc_relaydomains_count(user, rdomain):
- inc_limit_usage(user, 'relay_domains_limit')
-
-
-@events.observe('RelayDomainDeleted')
-def dec_relaydomains_count(rdomain):
- owner = get_object_owner(rdomain)
- dec_limit_usage(owner, 'relay_domains_limit')
- for rdomalias in rdomain.relaydomainalias_set.all():
- dec_rdomaliases_count(rdomalias)
-
-
-@events.observe('RelayDomainAliasCreated')
-def inc_rdomaliases_count(user, rdomalias):
- inc_limit_usage(user, 'relay_domain_aliases_limit')
-
-
-@events.observe('RelayDomainAliasDeleted')
-def dec_rdomaliases_count(rdomainaliases):
- if isinstance(rdomainaliases, RelayDomainAlias):
- rdomainaliases = [rdomainaliases]
- for rdomainalias in rdomainaliases:
- owner = get_object_owner(rdomainalias)
- dec_limit_usage(owner, 'relay_domain_aliases_limit')
diff --git a/modoboa/extensions/postfix_relay_domains/migrations/0001_initial.py b/modoboa/extensions/postfix_relay_domains/migrations/0001_initial.py
deleted file mode 100644
index 311a5dc0d..000000000
--- a/modoboa/extensions/postfix_relay_domains/migrations/0001_initial.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('admin', '0001_initial'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='RelayDomain',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(help_text='The domain name', unique=True, max_length=100, verbose_name='name')),
- ('target_host', models.CharField(help_text='Remote destination of this domain', max_length=255, verbose_name='target host')),
- ('enabled', models.BooleanField(default=True, help_text='Check to activate this domain', verbose_name='enabled')),
- ('verify_recipients', models.BooleanField(default=False, help_text='Check for valid recipients', verbose_name='verify recipients')),
- ('dates', models.ForeignKey(to='admin.ObjectDates')),
- ],
- options={
- 'ordering': ['name'],
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='RelayDomainAlias',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(help_text='The alias name', unique=True, max_length=100, verbose_name='name')),
- ('enabled', models.BooleanField(default=True, help_text='Check to activate this alias', verbose_name='enabled')),
- ('dates', models.ForeignKey(to='admin.ObjectDates')),
- ('target', models.ForeignKey(verbose_name='target', to='postfix_relay_domains.RelayDomain', help_text='The relay domain this alias points to')),
- ],
- options={
- 'abstract': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='Service',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(help_text='The service name', unique=True, max_length=100, verbose_name='name')),
- ],
- options={
- },
- bases=(models.Model,),
- ),
- migrations.AddField(
- model_name='relaydomain',
- name='service',
- field=models.ForeignKey(to='postfix_relay_domains.Service'),
- preserve_default=True,
- ),
- ]
diff --git a/modoboa/extensions/postfix_relay_domains/migrations/__init__.py b/modoboa/extensions/postfix_relay_domains/migrations/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modoboa/extensions/postfix_relay_domains/models.py b/modoboa/extensions/postfix_relay_domains/models.py
deleted file mode 100644
index 17807373e..000000000
--- a/modoboa/extensions/postfix_relay_domains/models.py
+++ /dev/null
@@ -1,210 +0,0 @@
-"""Relay domain related models."""
-
-from django.contrib.contenttypes import generic
-from django.db import models
-from django.db.models.manager import Manager
-from django.utils.translation import ugettext as _, ugettext_lazy
-
-import reversion
-
-from modoboa.core.models import ObjectAccess
-from modoboa.extensions.admin.models import AdminObject
-from modoboa.lib import parameters
-from modoboa.lib.exceptions import BadRequest, NotFound
-
-
-class RelayDomainManager(Manager):
-
- def get_for_admin(self, admin):
- """Return the relay domains belonging to this admin.
-
- The result is a ``QuerySet`` object, so this function can be used
- to fill ``ModelChoiceField`` objects.
- """
- if admin.is_superuser:
- return self.get_query_set()
- return self.get_query_set().filter(owners__user=admin)
-
-
-class ServiceManager(Manager):
-
- def load_from_master_cf(self):
- """Load services from the master.cf file.
-
- Parse the configuration file to update the service table. New
- entries are saved and outdated ones (ie. present in the
- database but not in the file) are removed.
- """
- with open(parameters.get_admin('MASTER_CF_PATH')) as fp:
- content = fp.read()
- services = []
- for line in content.split('\n'):
- if not line or line.startswith('#'):
- continue
- parts = line.strip().split()
- if len(parts) != 8:
- continue
- if parts[7] != 'smtp':
- continue
- srv, created = self.get_or_create(name=parts[0])
- services.append(parts[0])
- to_delete = []
- for service in self.all():
- if service.name not in services:
- to_delete.append(service.name)
- Service.objects.filter(name__in=to_delete).delete()
-
-
-class Service(models.Model):
-
- """Postfix service.
- """
- name = models.CharField(
- ugettext_lazy('name'), max_length=100, unique=True,
- help_text=ugettext_lazy('The service name')
- )
-
- objects = ServiceManager()
-
- def __str__(self):
- return self.name
-
-
-class RelayDomain(AdminObject):
-
- """Relay domain.
-
- A relay domain differs from a usual domaine because its final
- destination is not reached yet. It must be accepted by the MTA but
- it will then be transfered to another one.
- """
- name = models.CharField(
- ugettext_lazy('name'), max_length=100, unique=True,
- help_text=ugettext_lazy('The domain name')
- )
- target_host = models.CharField(
- ugettext_lazy('target host'), max_length=255,
- help_text=ugettext_lazy('Remote destination of this domain')
- )
- service = models.ForeignKey(Service)
- enabled = models.BooleanField(
- ugettext_lazy('enabled'),
- help_text=ugettext_lazy('Check to activate this domain'),
- default=True
- )
- verify_recipients = models.BooleanField(
- ugettext_lazy('verify recipients'),
- help_text=ugettext_lazy('Check for valid recipients'),
- default=False
- )
-
- owners = generic.GenericRelation(ObjectAccess)
-
- objects = RelayDomainManager()
-
- class Meta:
- ordering = ['name']
-
- @property
- def tags(self):
- return [
- {"name": "relaydomain", "label": _("Relay Domain"), "type": "dom"},
- {"name": self.service.name, "label": "%s:" % self.service.name,
- "type": "srv", "color": "info"}
- ]
-
- @property
- def aliases(self):
- return self.relaydomainalias_set
-
- def __str__(self):
- return self.name
-
- def to_csv(self, csvwriter):
- """Export this relay domain to CSV.
-
- :param csvwriter:
- """
- csvwriter.writerow(
- ["relaydomain", self.name, self.target_host,
- self.service.name, self.enabled, self.verify_recipients]
- )
- for rdalias in self.relaydomainalias_set.all():
- rdalias.to_csv(csvwriter)
-
- def from_csv(self, user, row):
- """Import a relay domain from CSV.
-
- :param user: user importing the relay domain
- :param str row: relay domain definition
- """
- if len(row) != 6:
- raise BadRequest(_("Invalid line"))
- self.name = row[1].strip()
- self.target_host = row[2].strip()
- self.service, created = Service.objects.get_or_create(
- name=row[3].strip())
- self.enabled = (row[4].strip() == 'True')
- self.verify_recipients = (row[5].strip() == 'True')
- self.save(creator=user)
-
- def post_create(self, creator):
- """Post creation actions.
-
- :param ``User`` creator: user whos created this relay domain
- """
- super(RelayDomain, self).post_create(creator)
- for rdomalias in self.relaydomainalias_set.all():
- rdomalias.post_create(creator)
-
-reversion.register(RelayDomain)
-
-
-class RelayDomainAlias(AdminObject):
-
- """Relay domain alias.
-
- """
- name = models.CharField(
- ugettext_lazy("name"), max_length=100, unique=True,
- help_text=ugettext_lazy("The alias name")
- )
- target = models.ForeignKey(
- RelayDomain, verbose_name=ugettext_lazy('target'),
- help_text=ugettext_lazy("The relay domain this alias points to")
- )
- enabled = models.BooleanField(
- ugettext_lazy('enabled'),
- help_text=ugettext_lazy("Check to activate this alias"),
- default=True
- )
-
- def __str__(self):
- return self.name
-
- def to_csv(self, csvwriter):
- """Export this relay domain alias to CSV.
-
- :param csvwriter:
- """
- csvwriter.writerow(
- ['relaydomainalias', self.name, self.target.name, self.enabled]
- )
-
- def from_csv(self, user, row):
- """Import a relay domain alias from CSV.
-
- :param user: user importing the relay domain alias
- :param str row: relay domain alias definition
- """
- if len(row) != 4:
- raise BadRequest(_("Invalid line"))
- self.name = row[1].strip()
- try:
- self.target = RelayDomain.objects.get(name=row[2].strip())
- except RelayDomain.DoesNotExist:
- raise NotFound(_("Relay domain %s does not exist" % row[2].strip()))
- self.enabled = (row[3].strip() == 'True')
- self.save(creator=user)
-
-reversion.register(RelayDomainAlias)
diff --git a/modoboa/extensions/postfix_relay_domains/modo_extension.py b/modoboa/extensions/postfix_relay_domains/modo_extension.py
deleted file mode 100644
index 4694f801a..000000000
--- a/modoboa/extensions/postfix_relay_domains/modo_extension.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# coding: utf-8
-
-"""Declare postfix_relay_domains extension and register it."""
-
-from django.utils.translation import ugettext_lazy
-
-from modoboa.core.extensions import ModoExtension, exts_pool
-from modoboa.lib import events, parameters
-
-
-EXTENSION_EVENTS = [
- "RelayDomainCreated",
- "RelayDomainDeleted",
- "RelayDomainModified",
- "RelayDomainAliasCreated",
- "RelayDomainAliasDeleted",
- "ExtraRelayDomainForm",
- "FillRelayDomainInstances"
-]
-
-
-class PostfixRelayDomains(ModoExtension):
-
- """Extension declaration."""
-
- name = "postfix_relay_domains"
- label = "Postfix relay domains"
- version = "1.0"
- description = ugettext_lazy("Relay domains support for Postfix")
-
- def load(self):
- from .app_settings import AdminParametersForm
-
- parameters.register(
- AdminParametersForm, ugettext_lazy("Relay domains")
- )
- events.declare(EXTENSION_EVENTS)
- from modoboa.extensions.postfix_relay_domains import general_callbacks
- if exts_pool.is_extension_installed("modoboa.extensions.limits"):
- import limits_callbacks
- if exts_pool.is_extension_installed("modoboa.extensions.amavis"):
- import amavis_callbacks
-
- def load_initial_data(self):
- """Create extension data."""
- from .models import Service
- for service_name in ['relay', 'smtp']:
- Service.objects.get_or_create(name=service_name)
-
- if not exts_pool.is_extension_installed("modoboa.extensions.limits"):
- return
- from .limits_callbacks import create_new_limits
- create_new_limits()
-
-exts_pool.register_extension(PostfixRelayDomains)
diff --git a/modoboa/extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js b/modoboa/extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js
deleted file mode 100644
index dddc99e8d..000000000
--- a/modoboa/extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * @module relay_domains
- * @desc Utility class to manage relay domains.
- */
-
-var RelayDomains = function(options) {
- this.initialize(options);
-};
-
-RelayDomains.prototype = {
- constructor: RelayDomains,
-
- defaults: {
- },
-
- initialize: function(options) {
- this.options = $.extend({}, this.defaults, options);
- admin.register_tag_handler("srv", this.srv_tag_handler);
- $(document).bind('domain_listing_refresh', this.listing_refresh_cb);
- },
-
- listing_refresh_cb: function() {
- $("a[name=delrelaydomain]").confirm({
- question: function() { return this.$element.attr('title'); },
- method: "DELETE",
- success_cb: $.proxy(admin.reload_listing, admin)
- });
- },
-
- launch_scan: function(e) {
- var $link = get_target(e);
-
- e.preventDefault();
- $.ajax({
- type: "POST",
- url: $link.attr("href"),
- global: false
- }).done(function(data) {
- var $widget = $('#id_service');
-
- $widget.empty();
- $.each(data, function(label, id) {
- $widget.append($(' ', {
- value: id,
- html: label
- }));
- });
- $('.modal-body').prepend(
- build_success_alert(gettext('Services updated'))
- );
- }).fail(function(jqxhr) {
- var result = $.parseJSON(jqxhr.responseText);
- $('.modal-body').prepend(
- build_error_alert(result[0])
- );
- });
- },
-
- domainform_cb: function() {
- $('#btnscan').click(this.launch_scan);
- $('input:text:visible:first').focus();
- $("#original_aliases").dynamic_input({
- input_added: function($row) {
- $row.find("label").html("");
- },
- input_removed: function($input) {
- $input.parents(".form-group").remove();
- return true;
- }
- });
- $(".submit").on('click', $.proxy(function(e) {
- simple_ajax_form_post(e, {
- formid: "rdomform",
- reload_on_success: false,
- success_cb: $.proxy(admin.reload_listing, admin)
- });
- }, this));
- },
-
- editdomain_form_cb: function() {
- this.domainform_cb();
- $(document).trigger('domform_init');
- },
-
- srv_tag_handler: function(tag, $link) {
- if (this.navobj.getparam(tag + "filter") === undefined && $link.hasClass(tag)) {
- var text = $link.attr("name");
- this.navobj
- .setparam("domfilter", "relaydomain")
- .setparam(tag + "filter", text)
- .update();
- if ($("a[name=dom]").length === 0) {
- $("#taglist").append(this.make_tag("relaydomain", "dom"));
- }
- $("#taglist").append(this.make_tag(text, tag));
- return true;
- }
- return false;
- }
-};
diff --git a/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/new_relaydomain_form.html b/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/new_relaydomain_form.html
deleted file mode 100644
index 8a349d160..000000000
--- a/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/new_relaydomain_form.html
+++ /dev/null
@@ -1,3 +0,0 @@
-{% extends "common/generic_modal_form.html" %}{% block formbody %}
-{% include "postfix_relay_domains/relaydomain_form.html" %}
-{% endblock %}
diff --git a/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/relaydomain_form.html b/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/relaydomain_form.html
deleted file mode 100644
index 13c6869a5..000000000
--- a/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/relaydomain_form.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% load form_tags %}
-{% render_field form.name %}
-{% render_field form.target_host %}
-{% include "postfix_relay_domains/service_field.html" with field=form.service label_width="col-sm-4" %}
-{% render_fields_group form "aliases" %}
-{% render_field form.enabled %}
-{% render_field form.verify_recipients %}
diff --git a/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html b/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html
deleted file mode 100644
index 0c843576a..000000000
--- a/modoboa/extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html
+++ /dev/null
@@ -1,4 +0,0 @@
-{% extends "common/generic_field.html" %}{% load i18n %}
-{% block extra_controls %}
-{% trans "Scan" %}
-{% endblock %}
diff --git a/modoboa/extensions/postfix_relay_domains/tests.py b/modoboa/extensions/postfix_relay_domains/tests.py
deleted file mode 100644
index 0a725161d..000000000
--- a/modoboa/extensions/postfix_relay_domains/tests.py
+++ /dev/null
@@ -1,209 +0,0 @@
-from django.core.urlresolvers import reverse
-
-from modoboa.core.factories import UserFactory
-from modoboa.extensions.admin import factories
-from modoboa.lib import parameters
-from modoboa.lib.tests import ModoTestCase
-from .factories import RelayDomainFactory, RelayDomainAliasFactory
-from .models import RelayDomain, RelayDomainAlias, Service
-
-
-class Operations(object):
-
- def _create_relay_domain(self, name, status=200):
- srv, created = Service.objects.get_or_create(name='dummy')
- values = {
- 'name': name, 'target_host': 'external.host.tld',
- 'service': srv.id, 'enabled': True
- }
- return self.ajax_post(
- reverse("postfix_relay_domains:relaydomain_add"),
- values, status
- )
-
- def _relay_domain_alias_operation(self, optype, rdomain, name, status=200):
- rdom = RelayDomain.objects.get(name=rdomain)
- values = {
- 'name': rdom.name, 'target_host': rdom.target_host,
- 'service': rdom.service.id
- }
- aliases = [alias.name for alias in rdom.relaydomainalias_set.all()]
- if optype == 'add':
- aliases.append(name)
- else:
- aliases.remove(name)
- for cpt, alias in enumerate(aliases):
- fname = 'aliases' if not cpt else 'aliases_%d' % cpt
- values[fname] = alias
- return self.ajax_post(
- reverse("postfix_relay_domains:relaydomain_change",
- args=[rdom.id]),
- values, status
- )
-
- def _check_limit(self, name, curvalue, maxvalue):
- l = self.user.limitspool.get_limit('%s_limit' % name)
- self.assertEqual(l.curvalue, curvalue)
- self.assertEqual(l.maxvalue, maxvalue)
-
-
-class RelayDomainsTestCase(ModoTestCase, Operations):
- fixtures = ['initial_users.json']
-
- def setUp(self):
- super(RelayDomainsTestCase, self).setUp()
- factories.populate_database()
- self.rdom = RelayDomainFactory(name='relaydomain.tld')
- RelayDomainAliasFactory(name='relaydomainalias.tld', target=self.rdom)
-
- def test_create_relaydomain(self):
- """Test the creation of a relay domain.
-
- We also check that unique constraints are respected: domain,
- relay domain alias.
-
- FIXME: add a check for domain alias.
- """
- self._create_relay_domain('relaydomain1.tld')
- rdom = RelayDomain.objects.get(name='relaydomain1.tld')
- self.assertEqual(rdom.target_host, 'external.host.tld')
- self.assertEqual(rdom.service.name, 'dummy')
- self.assertEqual(rdom.enabled, True)
- self.assertEqual(rdom.verify_recipients, False)
-
- resp = self._create_relay_domain('test.com', 400)
- self.assertEqual(resp['form_errors']['name'][0],
- 'A domain with this name already exists')
- resp = self._create_relay_domain('relaydomainalias.tld', 400)
- self.assertEqual(
- resp['form_errors']['name'][0],
- 'A relay domain alias with this name already exists'
- )
-
- def test_create_relaydomainalias(self):
- """Test the creation of a relay domain alias.
-
- We also check that unique constraints are respected: domain,
- relay domain.
-
- FIXME: add a check for domain alias.
- """
- self._relay_domain_alias_operation(
- 'add', self.rdom.name, 'relaydomainalias1.tld'
- )
- resp = self._relay_domain_alias_operation(
- 'add', self.rdom.name, 'test.com', 400
- )
- self.assertEqual(
- resp['form_errors']['aliases_2'][0],
- 'A domain with this name already exists'
- )
- resp = self._relay_domain_alias_operation(
- 'add', self.rdom.name, self.rdom.name, 400
- )
- self.assertEqual(
- resp['form_errors']['aliases_2'][0],
- 'A relay domain with this name already exists'
- )
-
- def test_edit_relaydomain(self):
- """Test the modification of a relay domain.
-
- Rename 'relaydomain.tld' domain to 'relaydomain.org'
- """
- values = {
- 'name': 'relaydomain.org', 'target_host': self.rdom.target_host,
- 'service': self.rdom.service.id
- }
- self.ajax_post(
- reverse('postfix_relay_domains:relaydomain_change',
- args=[self.rdom.id]),
- values
- )
- RelayDomain.objects.get(name='relaydomain.org')
-
- def test_edit_relaydomainalias(self):
- """Test the modification of a relay domain alias.
-
- Rename 'relaydomainalias.tld' domain to 'relaydomainalias.net'
- """
- values = {
- 'name': 'relaydomain.org', 'target_host': self.rdom.target_host,
- 'service': self.rdom.service.id, 'aliases': 'relaydomainalias.net'
- }
- self.ajax_post(
- reverse('postfix_relay_domains:relaydomain_change',
- args=[self.rdom.id]),
- values
- )
- RelayDomainAlias.objects.get(name='relaydomainalias.net')
- with self.assertRaises(RelayDomainAlias.DoesNotExist):
- RelayDomainAlias.objects.get(name='relaydomainalias.tld')
-
- def test_delete_relaydomain(self):
- """Test the removal of a relay domain
- """
- self.ajax_post(
- reverse("postfix_relay_domains:relaydomain_delete",
- args=[self.rdom.id]),
- {}
- )
- with self.assertRaises(RelayDomain.DoesNotExist):
- RelayDomain.objects.get(name='relaydomain.tld')
-
- def test_delete_relaydomainalias(self):
- """Test the remove of a relay domain alias
- """
- self._relay_domain_alias_operation(
- 'del', self.rdom.name, 'relaydomainalias.tld'
- )
- with self.assertRaises(RelayDomain.DoesNotExist):
- RelayDomain.objects.get(name='relaydomainalias.tld')
-
-
-class LimitsTestCase(ModoTestCase, Operations):
-
- def setUp(self):
- super(LimitsTestCase, self).setUp()
- from modoboa.extensions.limits.models import LimitTemplates
-
- for tpl in LimitTemplates().templates:
- parameters.save_admin('DEFLT_%s' % tpl[0].upper(), 2, app='limits')
- self.user = UserFactory.create(
- username='reseller', groups=('Resellers',)
- )
- self.clt.logout()
- self.clt.login(username='reseller', password='toto')
-
- def test_relay_domains_limit(self):
- self._create_relay_domain('relaydomain1.tld')
- self._check_limit('relay_domains', 1, 2)
- self._create_relay_domain('relaydomain2.tld')
- self._check_limit('relay_domains', 2, 2)
- resp = self._create_relay_domain('relaydomain3.tld', 403)
- self._check_limit('relay_domains', 2, 2)
- self.ajax_post(
- reverse('postfix_relay_domains:relaydomain_delete',
- args=[RelayDomain.objects.get(name='relaydomain2.tld').id]),
- {}
- )
- self._check_limit('relay_domains', 1, 2)
-
- def test_relay_domain_aliases_limit(self):
- self._create_relay_domain('relaydomain1.tld')
- self._relay_domain_alias_operation(
- 'add', 'relaydomain1.tld', 'relay_domain_alias1.tld'
- )
- self._check_limit('relay_domain_aliases', 1, 2)
- self._relay_domain_alias_operation(
- 'add', 'relaydomain1.tld', 'relay_domain_alias2.tld'
- )
- self._check_limit('relay_domain_aliases', 2, 2)
- self._relay_domain_alias_operation(
- 'add', 'relaydomain1.tld', 'relay_domain_alias3.tld', 403
- )
- self._check_limit('relay_domain_aliases', 2, 2)
- self._relay_domain_alias_operation(
- 'delete', 'relaydomain1.tld', 'relay_domain_alias2.tld'
- )
- self._check_limit('relay_domain_aliases', 1, 2)
diff --git a/modoboa/extensions/postfix_relay_domains/urls.py b/modoboa/extensions/postfix_relay_domains/urls.py
deleted file mode 100644
index a907cc799..000000000
--- a/modoboa/extensions/postfix_relay_domains/urls.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns(
- 'modoboa.extensions.postfix_relay_domains.views',
-
- url(r'^relaydomains/new/', 'create', name="relaydomain_add"),
- url(r'^relaydomains/(?P\d+)/edit/$', 'edit',
- name='relaydomain_change'),
- url(r'^relaydomains/(?P\d+)/delete/$', 'delete',
- name="relaydomain_delete"),
- url(r'^relaydomains/scan_services/$', 'scan_for_services',
- name="service_scan"),
-)
diff --git a/modoboa/extensions/postfix_relay_domains/views.py b/modoboa/extensions/postfix_relay_domains/views.py
deleted file mode 100644
index e95ec849b..000000000
--- a/modoboa/extensions/postfix_relay_domains/views.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import reversion
-from django.shortcuts import render
-from django.db import transaction
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext as _
-from django.views.decorators.http import require_http_methods
-from django.contrib.auth.decorators import (
- login_required, permission_required
-)
-from modoboa.lib import events
-from modoboa.lib.exceptions import PermDeniedException
-from modoboa.lib.web_utils import render_to_json_response
-from .models import RelayDomain, Service
-from .forms import RelayDomainForm, RelayDomainFormGeneral
-
-
-@login_required
-@permission_required("postfix_relay_domains.add_relaydomain")
-@transaction.commit_on_success
-@reversion.create_revision()
-def create(request, tplname="postfix_relay_domains/new_relaydomain_form.html"):
- events.raiseEvent("CanCreate", request.user, "relay_domains")
- if request.method == 'POST':
- form = RelayDomainFormGeneral(request.POST)
- if form.is_valid():
- rdom = form.save(request.user)
- rdom.post_create(request.user)
- return render_to_json_response(_("Relay domain created"))
- return render_to_json_response(
- {'form_errors': form.errors}, status=400
- )
-
- ctx = {"title": _("New relay domain"),
- "action_label": _("Create"),
- "action_classes": "submit",
- "action": reverse("postfix_relay_domains:relaydomain_add"),
- "formid": "rdomform",
- "form": RelayDomainFormGeneral()}
- return render(request, tplname, ctx)
-
-
-@login_required
-@permission_required("postfix_relay_domains.change_relaydomain")
-@reversion.create_revision()
-def edit(request, rdom_id, tplname='common/tabforms.html'):
- rdom = RelayDomain.objects.get(pk=rdom_id)
- if not request.user.can_access(rdom):
- raise PermDeniedException
- instances = {'general': rdom}
- events.raiseEvent("FillRelayDomainInstances", request.user, rdom, instances)
- return RelayDomainForm(request, instances=instances).process()
-
-
-@login_required
-@permission_required("postfix_relay_domains.delete_relaydomain")
-def delete(request, rdom_id):
- rdom = RelayDomain.objects.get(pk=rdom_id)
- if not request.user.can_access(rdom):
- raise PermDeniedException
- rdom.delete()
- return render_to_json_response(_('Relay domain deleted'))
-
-
-@login_required
-@permission_required("postfix_relay_domains.add_service")
-@require_http_methods(["POST"])
-def scan_for_services(request):
- try:
- Service.objects.load_from_master_cf()
- except IOError as e:
- return render_to_json_response([str(e)], status=500)
-
- return render_to_json_response(
- dict((srv.name, srv.id) for srv in Service.objects.all())
- )
From 7154181ea9fd1f13c3447dccc3674d5dc6c29054 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Feb 2015 15:07:47 +0100
Subject: [PATCH 08/25] Update translation files
---
modoboa/locale/cs_CZ/LC_MESSAGES/django.po | 2925 ++--------------
modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po | 154 +-
modoboa/locale/de/LC_MESSAGES/django.po | 2966 +---------------
modoboa/locale/de/LC_MESSAGES/djangojs.po | 153 +-
modoboa/locale/en/LC_MESSAGES/django.po | 2842 +---------------
modoboa/locale/en/LC_MESSAGES/djangojs.po | 146 +-
modoboa/locale/es/LC_MESSAGES/django.po | 3190 ++----------------
modoboa/locale/es/LC_MESSAGES/djangojs.po | 175 +-
modoboa/locale/fr/LC_MESSAGES/django.po | 2947 +---------------
modoboa/locale/fr/LC_MESSAGES/djangojs.po | 148 +-
modoboa/locale/it/LC_MESSAGES/django.po | 3096 +----------------
modoboa/locale/it/LC_MESSAGES/djangojs.po | 157 +-
modoboa/locale/nl_NL/LC_MESSAGES/django.po | 2917 ++--------------
modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po | 153 +-
modoboa/locale/pt_BR/LC_MESSAGES/django.po | 2908 +---------------
modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po | 153 +-
modoboa/locale/pt_PT/LC_MESSAGES/django.po | 2903 +---------------
modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po | 153 +-
modoboa/locale/ru/LC_MESSAGES/django.po | 3053 +----------------
modoboa/locale/ru/LC_MESSAGES/djangojs.po | 162 +-
modoboa/locale/sv/LC_MESSAGES/django.po | 2906 +---------------
modoboa/locale/sv/LC_MESSAGES/djangojs.po | 153 +-
22 files changed, 1922 insertions(+), 32438 deletions(-)
diff --git a/modoboa/locale/cs_CZ/LC_MESSAGES/django.po b/modoboa/locale/cs_CZ/LC_MESSAGES/django.po
index 15eb5b3d4..fa2d049bb 100644
--- a/modoboa/locale/cs_CZ/LC_MESSAGES/django.po
+++ b/modoboa/locale/cs_CZ/LC_MESSAGES/django.po
@@ -1,3107 +1,558 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Miroslav Abrahám , 2013-2015
msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2015-01-06 10:05+0000\n"
"Last-Translator: Miroslav Abrahám \n"
-"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/modoboa/language/cs_CZ/)\n"
+"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/"
+"modoboa/language/cs_CZ/)\n"
+"Language: cs_CZ\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: cs_CZ\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Obecné"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr "Nové verze Modoboa je k dispozici"
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Ověření"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Typ ověření"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Lokální"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Rozhraní pro ověřování přístupu"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Výchozí schéma hesel"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (slabé)"
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (slabé)"
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (slabé)"
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (slabé)"
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "žádné (slabé)"
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Použité schéma pro šifrování hesel schránek"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr "Počet cyklů"
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
-msgstr "Počet cyklů (použije se pouze u sha256crypt a sha512crypt). Hodnota musí být mezi 1000 a 999999999 včetně."
-
-#: core/app_settings.py:75
+msgstr ""
+"Počet cyklů (použije se pouze u sha256crypt a sha512crypt). Hodnota musí být "
+"mezi 1000 a 999999999 včetně."
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Tajný klíč"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Klíč používaný k šifrování/dešifrování hesel"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Nastavení LDAP"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Adresa serveru"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "IP adresa DNS jména LDAP serveru"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Port serveru"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Port TCP, který používá LDAP server"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Použít zabezpečené připojení"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Použít připojení SSL/TLS pro přístup k LDAP serveru"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Metoda ověření"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Vyhledat a spojit"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Přímé spojení"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Zvolte si metodu ověření, která se použije"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Spojení pomocí DN"
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
-msgstr "Rozlišovací jméno, které se použije při spojování s LDAP serverem. Ponechejte prázdné pro anonymní spojení."
-
-#: core/app_settings.py:127
+msgstr ""
+"Rozlišovací jméno, které se použije při spojování s LDAP serverem. "
+"Ponechejte prázdné pro anonymní spojení."
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Heslo spojení"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
-msgstr "Heslo, které se použije při spojování s LDAP serverem (při výběru DN spojení)."
-
-#: core/app_settings.py:139
+msgstr ""
+"Heslo, které se použije při spojování s LDAP serverem (při výběru DN "
+"spojení)."
+#: core/app_settings.py:134
msgid "Users search base"
msgstr "Základna struktury uživatelů"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "Rozlišovací jméno základny struktury používané pro hledání uživatelů"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Vyhledávací filtr"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
-msgstr "Volitelný filtr (např. '(objectClass=osoba)'). Aby byl filtr platný, je nezbytné jen uzavřít do závorek."
-
-#: core/app_settings.py:160
+msgstr ""
+"Volitelný filtr (např. '(objectClass=osoba)'). Aby byl filtr platný, je "
+"nezbytné jen uzavřít do závorek."
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Šablona uživatelského DN"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
"placeholder (ie. %(user)s)"
-msgstr "Šablona použitá pro tvorbu uživatelského rozlišovacího jména (DN). Měla by obsahovat jeden zástupný řetězec (tj. %(user)s)."
-
-#: core/app_settings.py:171
+msgstr ""
+"Šablona použitá pro tvorbu uživatelského rozlišovacího jména (DN). Měla by "
+"obsahovat jeden zástupný řetězec (tj. %(user)s)."
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Atribut hesla"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Atribut používaný pro ukládání hesel uživatelů"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
-msgstr "Volba určující, jestli je nebo není LDAP server serverem Active Directory"
-
-#: core/app_settings.py:185
+msgstr ""
+"Volba určující, jestli je nebo není LDAP server serverem Active Directory"
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Správcovské skupiny"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
-"Members of those LDAP Posix groups will be created as domain administrators."
-" Use ';' characters to separate groups."
-msgstr "Členové těchto LDAP Posix skupin budou automaticky vytvořeni jako správci domény. Pro oddělení skupin použijte ';'."
-
-#: core/app_settings.py:195
+"Members of those LDAP Posix groups will be created as domain administrators. "
+"Use ';' characters to separate groups."
+msgstr ""
+"Členové těchto LDAP Posix skupin budou automaticky vytvořeni jako správci "
+"domény. Pro oddělení skupin použijte ';'."
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Základna struktury skupin"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "Rozlišovací jméno základny struktury používané pro hledání skupin"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Různé"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Interval aktualizací upozornění"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Interval mezi aktualizacemi upozornění na stránce"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Zkontrolovat verzi"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Automaticky kontrolovat dostupnost nové verze"
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Maximální stáří záznamu"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "Maximální stáří záznamu ve dnech"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Položek na stránce"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Počet zobrazených položek na stránce"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Výchozí přesměrování aplikace"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
-msgstr "Výchozí přesměrování, které se použije, pokud není žádná aplikace specifikována"
-
-#: core/app_settings.py:268
+msgstr ""
+"Výchozí přesměrování, které se použije, pokud není žádná aplikace "
+"specifikována"
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Klíč musí mít délku 16, 24 nebo 32 znaků"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Neplatná syntaxe"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Neplatný počet cyklů"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Toto pole je vyžadováno"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Zobrazení"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Preferovaný jazyk"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Preferovaný jazyk pro zobrazení stránek"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Uživatelské jméno"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Heslo"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Původní heslo"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Nové heslo"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Potvrzení"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Původní heslo se neshoduje"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Hesla se neshodují"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr "heslo"
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr "poslední přihlášení"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Nemůžete smazat vlastní účet"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Nebylo možné změnit heslo: LDAP modul není instalován"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "účet"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Neplatný řádek"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "Nemůžete importvat účet s vyšším oprávněním, než máte vy sám"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "Běžný uživatel '%s' musí mít nastavenou platnou emailovou adresu"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "pole uživatelského jména a emailu se nesmí pro '%s' lišit"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "povoleno"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Zatrhněte pole pro povolení tohoto rozšíření"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "přidáno"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "upraveno"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s uživatelem %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "smazáno"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Rozšíření"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Zvolte rozšíření, která chcete použít"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Jméno"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Verze"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Popis"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Uložit"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Informace"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Různé informace o Modoboa"
-
#: core/templates/core/information.html:5
msgid "An update is available!"
msgstr "Je dostupná aktualizace!"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
"\n"
-" Modoboa %(version)s is available for download. The list of all changes is available here .\n"
+" Modoboa %(version)s is available for download. The list "
+"of all changes is available here .\n"
" "
-msgstr "\nModoboa %(version)s je dostupná ke stažení. Seznam všech změn je k dispozici zde ."
-
+msgstr ""
+"\n"
+"Modoboa %(version)s je dostupná ke stažení. Seznam všech "
+"změn je k dispozici zde ."
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "se aktuálně používá."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Aktivní uživatelé"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Název skupiny"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Poslední přihlášení"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Záznamy"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Dříve v Modoboa..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Datum"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Úroveň"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Zaznamenal"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Zpráva"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Parametry"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Nastavit Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Uložit"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Nastavení Modoboa"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Nastavení"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Možnosti"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Nastavit Modoboa"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Profil"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Aktualizovat osobní informace"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Aktualizovat"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Odhlásit se"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Parametry uloženy"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Úpravy byly uloženy."
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Uživatel '%s' se úspěšně přihlásil"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
-msgstr "Vaše uživatelské jméno nebo heslo se neshodují. Zkuste to prosím znovu."
-
-#: core/views/auth.py:72
+msgstr ""
+"Vaše uživatelské jméno nebo heslo se neshodují. Zkuste to prosím znovu."
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Uživatel '%s' se odhlásil"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profil aktualizován"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Možnosti uloženy"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Testovací zprávy"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Poslat vir"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Poslat spam"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Zpráva odeslána"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
"Welcome to the online demo! \n"
"Warning: the demo's concent is resetted every two hours.
\n"
-"To try the demo, the following users are available (username/password ):
\n"
+"To try the demo, the following users are available (username/password"
+"i>):
\n"
"\n"
" A super administrator : admin/password \n"
" A domain administrator : admin@demo.local/admin \n"
" A simple user : user@demo.local/user \n"
" \n"
"Please report any issue or give any suggestion to \n"
-" the mailing list .
\n"
-msgstr "\nVítejte v online demo verzi! \nUpozornění: obsah této demo verze je automaticky obnoven každé 2 hodiny.
\nPro vyzkoušení demo verze jsou dostupní tito uživatelé (jméno/heslo ):
\n\n Super správce : admin/password \n Správce domény: admin@demo.local/admin \n Uživatel: user@demo.local/user \n \nNahlašte prosím jakékoli objevené problémy nebo vaše návrhy přes\n emailový seznam .
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Konzola správce"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Webová konzola pro správu domén, účtů a aliasů"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr "Správa"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Domény"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Identity"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Přeposlat"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Import účtu nebyl úspěšný (%s): doména neexistuje"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "Schránka %s již existuje"
-
-#: extensions/admin/__init__.py:186
-#, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Import účtu selhal (%s): chybná hodnota kvóty"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr "doménový alias"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Schránky"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Spravovat schránky v souborovém systému"
-
-#: extensions/admin/app_settings.py:19
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr "Přejmenovat nebo odstranit schránky v souborovém systému, pokud jsou přejmenovány nebo odstraněny v Modoboa"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Majitel schránky"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "Účet UNIXu, který vlastní schránky v souborovém systému"
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr "Výchozí kvóta domény"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr "Výchozí kvóta (v MB), které se použije u nově vytvořených domén bez uvedené hodnoty kvóty. Hodnota 0 znamená, že se kvóta nepoužívá."
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Automatické odstranění účtu"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr "Když je schránka odstraněná, odstranit také přiřazený účet uživatele"
-
-#: extensions/admin/app_settings.py:49
-msgid "Automatic domain/mailbox creation"
-msgstr "Automatické vytvoření domény/schránky"
-
-#: extensions/admin/app_settings.py:52
-msgid ""
-"Create a domain and a mailbox when an account is automatically created."
-msgstr "Při založení účtu automaticky vytvořit doménu a schránku."
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr "Musí se jednat o kladné číslo"
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr "Schránka je vyžadována"
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr "Název uživatele. U běžných uživatelů musí být uvedena platná e-mailová adresa nebo u administrátorů schránka."
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Role"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Vybrat"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Jaká úroveň oprávnění bude tomuto uživateli nastavena"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Vložte stejné heslo jako v poli výše, pro jeho ověření."
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Povoleno"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Obě pole s heslem se neshodují."
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "Nemůžete zakázat váš vlastní účet"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "E-mail"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Kvóta"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr "Kvóta pro tuto chránku v MB. Definujte vlastní hodnotu nebo použijte výchozí hodnotu domény. Ponechejte prázdné pro neomezenou kvótu (není povoleno správcům domény)."
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Alias(y)"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr "Alias(y) této schránky. Vložte pouze jeden alias na řádek, stiskněte ENTER pro vložení dalšího aliasu. Pro vytvoření doménového koše vložte '*' (např. *@domena.cz)."
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "Doména neexistuje"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Doména(y)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Doména(y) pod správou uživatele"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Mail"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Oprávnění"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Účet aktualizován"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Nový účet"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Účet vytvořen"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "Emailová adresa"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr "Distribuční seznam adres. Pro vytvoření doménového koše vložte znak '*' (např. *@domena.cz)."
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Příjemci"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr "Schránka/Schránky, na kterou/které bude tento alias odkazovat. Uveďte na řádek pouze jednu adresu; pro vložení další adresy stiskněte po vložení ENTER."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "Nemáte oprávnění k přístupu k této doméně"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Neplatná schránka"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Místní příjemce %s nebyl nalezen"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "Příjemce %s je již vložen"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Nebyl určen příjemce"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr "Výchozí kvóta v MB pro schránky. Ponechejte prázdné pro výchozí nastavení kvóty."
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr "Alias(y) této domény. Uveďte na řádek pouze jeden alias; pro vložení dalšího aliasu stiskněte po vložení ENTER."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr "%s s tímto názvem již existuje"
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr "doména"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Vytvořit správce domény"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Automaticky vytvořit správce této domény"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr "Jméno správce. Nevkládejte sem název domény, název bude automaticky doplněn."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Vytvořit aliasy"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Automaticky vytvořit běžné aliasy pro tuto doménu"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Neplatný formát"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "Uživatel '%s' již existuje"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Doména upravena"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Možnosti"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Nová doména"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Doména vytvořena"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Název souboru"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Oddělovač"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Příjemce(i)"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Uveďte jednoho nebo více příjemců oddělených pomocí ','"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Ponechat místní kopie"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr "Přeposílat zprávy a ukládat kopie do místní schránky"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr "Nemůžete nastavit přeposílání na místní adresu. Požádejte správce o vytvoření aliasu."
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Vybrat soubor"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Při výskytu chyby pokračovat"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Nepovažovat duplikáty objektů za chybu"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Zašifrovat hesla"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr "Zatrhněte toto pole, pokud hesla ve vašem souboru nejsou zašifrována"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "adresa"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just"
-" enter an * character."
-msgstr "Alias adresy (bez části označující doménu). Pro vytvoření doménového koše vložte znak '*'."
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "schránky"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "Schránky, na které tento alias odkazuje"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Aliasy, na které tento alias odkazuje"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Zatrhněte pole pro povolení tohoto aliasu"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "distribuční seznam"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "přeposlat"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Neplatný řádek: %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "Doména '%s' neexistuje"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "název"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "Doménové jméno"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Zatrhněte pole pro povolení této domény"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr "Doména"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr "Neplatná hodnota kvóty u domény '%s'"
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "Název aliasu"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "cíl"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "Doména, na kterou tento alias odkazuje"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Neznámá doména %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Adresa schránky (bez části @doména.tld)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Nebylo možné zjistit umístění schránky (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "Zvolená kvóta je větší než povolené omezení domény (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "Kvóta je vyžadována"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-msgid "Domain is disabled"
-msgstr "Doména je zakázána"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "MB"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr "Nemůžete vytvořit nového správce domény"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Statistiky"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-msgid "Domains and identities"
-msgstr "Domény a identity"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr "Globální počitadla"
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr "Typ"
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-msgid "Quantity"
-msgstr "Počet"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Doménové aliasy"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr "Počitadla dle domén"
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Značky"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Akce"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-msgid "disabled"
-msgstr "zákázáno"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Správci"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr " Nebyl určen správce domény"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Datum vytvoření"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Datum poslední změny"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Aliasy schránek"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Automaticky přesměrovat emaily na jinou adresu"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Celé jméno/Příjemce"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Nápověda"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Importuji..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Zvolte hodnotu"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Použít výchozí hodnotu domény"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Adresa"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Hodnota"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Omezení"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Využití (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Hledat"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "Aktivovaný"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "Aktivovaná"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-msgid "List domains"
-msgstr "Seznam domén"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Přidat doménu"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Import"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Export"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Seznam identit"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Seznam kvót"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Přidat účet"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Přidat alias"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Přidat přeposílání"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Přidat distribuční seznam"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Zobrazit seznam identit domény"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "Smazat %s?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Odstranit toto oprávnění"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Alias s tímto názvem již existuje"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Vytvořit"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Nový distribuční seznam"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Distribuční seznam vytvořen"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Nový alias"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias vytvořen"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Nové přeposílání"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Přeposílání vytvořeno"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Distribuční seznam upraven"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Přeposílání upraveno"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Alias upraven"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "Nemůžete smazat vlastní doménu"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Doména smazána"
-msgstr[1] "Domény smazány"
-msgstr[2] "Domén smazáno"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Exportovat identity"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Exportovat domény"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Neplatný požadavek"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Účet smazán"
-msgstr[1] "Účty smazány"
-msgstr[2] "Účtů smazáno"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
+" the "
+"mailing list . \n"
+msgstr ""
+"\n"
+"Vítejte v online demo verzi! \n"
+"Upozornění: obsah této demo verze je automaticky obnoven každé 2 "
+"hodiny.
\n"
+"Pro vyzkoušení demo verze jsou dostupní tito uživatelé (jméno/heslo"
+"i>):
\n"
"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
+" Super správce : admin/password \n"
+" Správce domény: admin@demo.local/admin \n"
+" Uživatel: user@demo.local/user \n"
" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr "Nahrajte CSV soubor, který bude mít jednotlivé řádky v některém z uvedených formátů:\n\ndomain; název; kvóta, povoleno \ndomainalias; název; cílová doména; povoleno \n%s\n \nPrvní element každého řádku je povinný a musí být shodný s některou z předchozích hodnot.
\nMůžete také použít jiný oddělovač hodnot.
\n"
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Importovat domény"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "Objekt již existuje: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d objektů úspěšně importováno"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr "Nahrajte CSV soubor, který bude mít jednotlivé řádky v některém z uvedených formátů:\n\naccount; přihlašovací jméno; heslo; křestní jméno; příjmení; povoleno; skupina; adresa; kvóta; [, doména, ...] \nalias; adresa; povoleno; interní příjemce \nforward; adresa; povoleno; externí příjemce \ndlist; adresa; povoleno; příjemce; příjemce; ... \n \nPrvní element každého řádku je povinný a musí být shodný s některou z předchozích hodnot.
\nMůžete také použít jiný oddělovač hodnot.
\n"
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Importovat identity"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Přeposílání aktualizováno"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Jednoduché rozhraní pro správu amavis"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Karanténa"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Nastavení karantény"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Maximální stáří zprávy"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr "Maximální doba karantény zpráv (ve dnech) před jejich smazáním"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Odblokování zpráv"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Odstranit odblokované zprávy"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr "Odstranit zprávy, které jsou označeny jako odblokované, při čištění databáze"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Režim připojení amavis"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Používaný režim pro přístup k PDP serveru"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "Adresa PDP serveru"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "adresa PDP serveru (v režimu inet)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "Port PDP serveru"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "port PDP serveru (v režimu inet)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "Socket PDP serveru"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Cesta k socketu PDP serveru (v režimu unix)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Umožnit přímé odbokování"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Umožnit napřímo uživatelům doblokovat jejich zprávy"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Povolit samoobslužný režim"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Aktivovat samoobslužný režim"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Odesílatel upozornění"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "E-mailová adresa používaná k zasílání upozornění"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr "Manuální učení"
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr "Povolit manuální učení"
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr "Povolit super správcům manuálně učit Spamassassin"
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr "Je Spamassassin lokální?"
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr "Volba určující, jestli je Spamassassin provozován na stejném serveru jako Modoboa"
-
-#: extensions/amavis/app_settings.py:99
-msgid "Default user"
-msgstr "Výchozí uživatel"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr "Jméno uživatele, který je vlastníkem výchozí bayesian databáze"
-
-#: extensions/amavis/app_settings.py:107
-msgid "Spamd address"
-msgstr "Adresa spamd"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr "IP adresa, na které je možné komunikovat se spamd"
-
-#: extensions/amavis/app_settings.py:113
-msgid "Spamd port"
-msgstr "Port spamd"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr "Port TCP, který používá spamd"
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr "Povolit manuální účení dle jednotlivých domén"
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr "Povolit správcům domén manuálně učit Spamassassin (v rámci vyhrazených databází jednotlivých domén)"
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr "Povolit manuální účetní dle jednotlivých uživatelů"
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr "Povolit uživatelům manuálně učit Spamassassin (v rámci vyhrazené databáze)"
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Počet zobrazených zpráv na stránce"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Nastavit maximální počet zobrazených zpráv na stránce"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr "Globální databáze"
-
-#: extensions/amavis/forms.py:94
-msgid "Domain's database"
-msgstr "Databáze domény"
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr "Uživatelská databáze"
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr "Nevyřízené požadavky"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Filtr obsahu"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "Spojení s amavis selhalo: %s"
-
-#: extensions/amavis/lib.py:131
-msgid "No recipient found"
-msgstr "Žádný příjemce nebyl nalezen"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Filtr virů"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "ano"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "ne"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "výchozí"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr "Obcházet nebo neobcházet kontrolu zpráv na viry. Pokud zvolíte 'výchozí', bude se nastavení řídit globálním nastavením."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Filtr nevyžádané pošty"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr "Obcházet nebo neobcházet kontrolu zpráv na nevyžádanou poštu. Pokud zvolíte 'výchozí', bude se nastavení řídit globálním nastavením."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Filtr zakázané pošty"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr "Obcházet nebo neobcházet kontrolu zpráv na zakázanou poštu. Pokud zvolíte 'výchozí', bude se nastavení řídit globálním nastavením."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Označení spamu"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global"
-" settings."
-msgstr "Upravit předmět nevyžádané zprávy uvedeným textem. Pro zachování globálního nastavení serveru zatrhněte 'výchozí'."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Vyprázdnit karanténu"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Zpráva smazána"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d zpráva úspěšně smazána"
-msgstr[1] "%(count)d zprávy úspěšně smazány"
-msgstr[2] "%(count)d zpráv úspěšně smazáno"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Požadavek odeslán"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Zprávy odblokována"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d požadavek odeslán"
-msgstr[1] "%(count)d požadavky odeslány"
-msgstr[2] "%(count)d požadavků odesláno"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d zpráva úspěšně odblokována"
-msgstr[1] "%(count)d zprávy úspěšně odblokovány"
-msgstr[2] "%(count)d zpráv úspěšně odblokováno"
-
-#: extensions/amavis/views.py:360
-#, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d zpráva úspěšně zpracována"
-msgstr[1] "%(count)d zprávy úspěšně zpracovány"
-msgstr[2] "%(count)d zpráv úspěšně zpracováno"
-
-#: extensions/amavis/views.py:394
-msgid "Select a database"
-msgstr "Vybrat databázi"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr "Ověřit"
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Nevyřízené požadavky na odblokování"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Mezní hodnoty"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "nebo více je spam"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "nebo více zahodí spam zprávu"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr "Hodnota"
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "Komu"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "Od"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Předmět"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-msgid "Released"
-msgstr "Odblokováno"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-msgid "Marked as spam"
-msgstr "Označeno jako spam"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-msgid "Marked as non-spam"
-msgstr "Označeno jako vyžádaná správa"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Nastavení karantény"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr "Vybrat"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr "Vyčistit"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Vir"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr "Špatné záhlaví"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Špatný MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr "Zakázaná pošta"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Odblokovat"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Smazat"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-msgid "Mark as spam"
-msgstr "Označit jako spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr "Označit jako vyžádanou zprávu"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Všechny zprávy"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr "Vše"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr "Pouze čisté"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr "Pouze spamy"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr "Pouze viry"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr "Pouze špatné záhlaví"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr "Pouze špatný MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr "Pouze zakázaná pošta"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] "\n%(counter)s požadavek na odblokování čeká na vyřízení.\n"
-msgstr[1] "\n%(counter)s požadavky na odblokování čekají na vyřízení.\n"
-msgstr[2] "\n%(counter)s požadavků na odblokování čeká na vyřízení.\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Náhled:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "Od:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "Komu:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Datum:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Předmět"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Úkony na zprávě:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Navštivte stránku %(listingurl)s pro zobrazení kompletního seznamu."
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Zpět"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Zobrazit úplné záhlaví"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr "Každému správci dostupné zdroje omezující počet objektů, které mohou správci vytvořit"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Omezení"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Výchozí omezení"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Správci domén"
-
-#: extensions/limits/app_settings.py:15
-msgid ""
-"Maximum number of allowed domain administrators for a new administrator"
-msgstr "Maximální povolený počet správců domény (nastavení nového správce)"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Maximální povolený počet domén (nastavení nového správce)"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr "Maximální povolený počet doménových aliasů (nastavení nového správce)"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Maximální povolený počet schránek (nastavení nového správce)"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Maximální povolený počet aliasů (nastavení nového správce)"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Neplatné omezení"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Vaše zdroje nebyly dosud definovány"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "Nemáte oprávnění nastavovat neomezené hodnoty"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Distributor"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Zdroje"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s: limit byl dosažen"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Nedostatek zdrojů"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr "Maximální povolený počet správců domény, které může tento uživatel vytvořit"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Maximální povolený počet domén, které může tento uživatel vytvořit"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Maximální povolený počet doménových aliasů, které může tento uživatel vytvořit"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Maximální povolený počet schránek, které může tento uživatel vytvořit"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr "Maximální povolený počet aliasů chránek, které může tento uživatel vytvořit"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "nedefinováno"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "neomezeno"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Využití zdrojů"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Funkce automatické odpovědi (vacation) Postfix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Automatické odpovědi"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Interval automatické odpovědi"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr "Interval v sekundách mezi dvěmi automatickými odpověďmi stejnému příjemci"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr "Výchozí předmět"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr "Jsem nedostupný"
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr "Výchozí předmět, který se použije u nově vytvořených automatických odpovědí"
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr "Výchozí obsah"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr "V současné době nejsem dostupný. Odpovím Vám ihned, jakmile se vrátím zpět.\n\nS pozdravem,\n%(name)s\n"
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr "Výchozí obsah, který se použije u nově vytvořených automatických odpovědí. Token '%(name)s' bude automaticky nahrazen celým jménem uživatele."
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr "Povolit automatickou odpověď od uvedeného data"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Do"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Povolit automatické odpovědi až do uvedeného data"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Zvolené datum je v minulosti"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr "Musí být větší než datum začátku"
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Automatická odpověď"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr "Povolit automatickou odpověď"
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr "Povolit nebo zakázat automatickou odpověď"
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "předmět"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "Předmět, který se vloží do odesílaných emailů"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "obsah"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "Obsah, který se vloží do odesílaných emailů"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Povolit/Zakázat automatickou odpověď"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Automatická odpověď byla aktualizována."
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr "Vložte zprávu, která se během vaší nepřítomnosti automaticky odešle"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr "Podpora relay domén v Postfix"
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr "Relay domény"
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr "Cesta k Postfix souboru master.cf"
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr "Cesta ke konfiguračnímu souboru master.cf"
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr "Alias(y) této relay domény. Vložte pouze jeden alias na řádek, stiskněte ENTER pro vložení dalšího aliasu."
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr "alias relay domény"
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr "relay doména"
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr "Relay doména upravena"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr "Přidat relay doménu"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr "Maximální povolený počet relay domén, které může tento uživatel vytvořit"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr "Aliasy relay domény"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr "Maximální povolený počet aliasů relay domény, které může tento uživatel vytvořit"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr "\nrelay doména; název; cílový server; služba; povoleno; ověřit příjemce \nalias relay domény; název; cíl; povoleno \n"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr "Maximální povolený počet relay domén, které může vytvořit nový správce"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr "Maximální povolený počet aliasů relay domény, které může vytvořit nový správce"
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr "Název služby"
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr "cílový server"
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr "Vzdálený cíl této domény"
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr "ověřit příjemce"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr "Kontrola platných příjemců"
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr "Relay doména"
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr "Relay doména, na kterou tento alias odkazuje"
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr "Relay doména %s neexistuje"
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr "Relay doména vytvořena"
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr "Nová relay doména"
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr "Relay doména smazána"
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr "Prohledat"
-
-#: extensions/radicale/__init__.py:34
-msgid "Radicale management"
-msgstr "Nastavení serveru Radicale"
-
-#: extensions/radicale/__init__.py:38
-msgid ""
-"Management frontend for Radicale, a simple calendar and contact server."
-msgstr "Nastavení rozhraní Radicale, jednoduchého serveru pro kalendáře a kontakty."
-
-#: extensions/radicale/app_settings.py:11
-msgid "Server settings"
-msgstr "Nastavení serveru"
-
-#: extensions/radicale/app_settings.py:15
-msgid "Server URL"
-msgstr "URL adresa serveru"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr "URL adresa serveru Radicale. Adresa bude použita k vytvoření adres kalendářů."
-
-#: extensions/radicale/app_settings.py:24
-msgid "Rights management"
-msgstr "Nastavení oprávnění"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr "Cesta k souboru s právy"
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr "Cesta k souboru, který obsahuje seznam oprávnění"
-
-#: extensions/radicale/app_settings.py:36
-msgid "Allow calendars administration"
-msgstr "Povolit správu kalendářů"
-
-#: extensions/radicale/app_settings.py:39
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr "Povolit správcům domén spravovat kalendáře uživatelů (číst a zapisovat)"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr "Číst"
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr "Psát"
-
-#: extensions/radicale/forms.py:134
-#, python-format
-msgid "Mailbox %s does not exist"
-msgstr "Schránka %s neexistuje"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr "Oprávnění"
-
-#: extensions/radicale/forms.py:162
-msgid "New calendar"
-msgstr "Nový kalendář"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-msgid "Calendar created"
-msgstr "Kalendář vytvořen"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-msgid "Calendar updated"
-msgstr "Kalendář aktualizován"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr "Kalendáře"
-
-#: extensions/radicale/models.py:94
-msgid "User"
-msgstr "Uživatel"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr "Sdíleno"
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-msgid "Calendar removed"
-msgstr "Kalendář odstraněn"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr "Nový sdílený kalendář"
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr "Uložit"
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr "Pro přístup k tomuto kalendáři použijte následující adresu:"
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr "Majitel"
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-msgid "Add calendar"
-msgstr "Přidat kalendář"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr "Přidat sdílený kalendář"
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr "Zobrazit detaily kalendáře"
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr "Upravit %s"
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Doplněk pro jednoduchou tvorbu filtrů zpráv na serveru"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "Sieve filtry"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Filtry zpráv"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "Nastavení ManageSieve"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Adresa vašeho serveru ManegeSieve"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "Port, na kterém naslouchá váš ManageSieve server"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Připojit pomocí STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Použít rozšíření STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Režim ověření"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Preferovaný režim ověření"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Režim úpravy"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Zvolte režim editoru textu, ve kterém si přejete pracovat"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Zatrhněte pole pro povolení této sady filtrů"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Všechna pravidla"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Alespoň jedno z pravidel"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "obsahuje"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "neobsahuje"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "je"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "není"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Odesílatel"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Příjemce"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Kopie"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Velikost"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "Je větší než"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "Je menší než"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Přesunout zprávu do"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Přesměrovat zprávu na"
-
-#: extensions/sievefilters/forms.py:110
-msgid "Wrong filter name"
-msgstr "Chybný název filtru"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr "Spojení se serverem ManageSieve selhalo, zkontrolujte nastavení"
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Nedostatek prostoru na serveru"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Nebylo možné získat sadu filtrů"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Nový filtr"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filtr vytvořen"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Upravit filtr"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filtr upraven"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filtr odstraněn"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Nezdařilo se odstranit filtr"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Sada filtrů uložena"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Sada filtrů vytvořena"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Vytvořit novou sadu filtrů"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Sada filtrů vymazána"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Sada filtrů povolena"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Podmínky"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Aktivní"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Dosud nebyl vytvořen žádný filtr"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Sady filtrů"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "aktivní"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr "Dosud nebyla vytvořena žádná sada filtrů. Aby bylo možné vytvořit filtry, je nejprve potřeba vytvořit sadu filtrů."
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Nová sada filtrů"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Uložit sadu filtrů"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Aktitovat sadu filtrů"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Odstranit sadu filtrů"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Stáhnout"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Odstranit tento filtr"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Posunout tento filtr nahoru"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Posunout tento filtr dolů"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Grafické statistiky emailového provozu s použitím RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Grafické statistiky"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Cesta k souboru záznamů"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Cesta k souboru záznamů, který se používá pro sběr statistických informací"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Adresář pro RRD soubory"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Cesta k adresáři, ve kterém budou ukládány RRD soubory"
-
-#: extensions/stats/graphics.py:98
-msgid "Average traffic (msgs/min)"
-msgstr "Průměrný provoz (zprávy/min)"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "odeslané zprávy"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "přijaté zprávy"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "nedoručené zprávy"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "odmítnuté zprávy"
-
-#: extensions/stats/graphics.py:112
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Průměrná velikost provozu (bajtů/min)"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "doručená velikost"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "odeslaná velikost"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Provoz emailů"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Žádné statistiky nejsou dostupné"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Den"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Týden"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Měsíc"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Rok"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr "Vlastní"
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Nastaveno neznámé zobrazení"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Neplatně nastavený vlastní časový interval"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Hledat doménu"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Uložit"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Jednoduchý IMAP webmail"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Maximální velikost přílohy"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Maximální velikost přílohy v Bajtech (nebo KB, MB, GB, pokud je uvedeno)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "Nastavení IMAP"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Adresa vašeho IMAP serveru"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Použít zabezpečené připojení pro přístup k IMAP serveru"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Port, na kterém naslouchá váš IMAP server"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "Nastavení SMTP"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Adresa vašeho SMTP serveru"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Režim zabezpečeného připojení"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Nic"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Použít zabezpečené připojení pro přístup k SMTP serveru"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Port, na kterém naslouchá váš SMTP server"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Ověření vyžadováno"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "Server vyžaduje ověření"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Výchozí režim zobrazení zprávy"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "Výchozí režim, který se použije pro zobrazení zprávy"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Povolit zobrazení HTML odkazů"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Povolit/Zakázat zobrazení HTML odkazů"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Nastavuje maximální počet zobrazených zpráv na stránce"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Automatické obnovení stránky"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Automatické načítání obsahu složky (v sekundách)"
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr "Šířka sloupce schránek"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr "Šířka sloupce schránek"
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Složka koše"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Složka pro smazané zprávy"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Složka odeslané pošty"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Složka pro kopie odeslaných zpráv"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Složka konceptů"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Složka pro koncepty zpráv"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Vytváření zpráv"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Výchozí editor"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "Výchozí editor textu, který se použije pro vytváření zpráv"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Text podpisu"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Emailový podpis uživatele"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr "Hodnota musí být kladné číslo (> 0)"
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Odpověď serveru"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Neznámá akce"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "BCC"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Webmail"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d zpráva smazána"
-msgstr[1] "%(count)d zprávy smazány"
-msgstr[2] "%(count)d zpráv smazáno"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Vyprázdnit schránku"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Schránka vytvořena"
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Vytvořit novou schránku"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Upravit schránku"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Schránka aktualizována"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Nebylo možné uložit přílohu:"
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "Příloha je příliš velká (omezení: %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Přílohy"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Neplatný dotaz"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Nebylo možné odstranit přílohu:"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Neznámá příloha"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "napsal/a:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Původní zpráva"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Nebylo možné zjistit hierarchický oddělovač"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "Spojení se serverem IMAP selhalo: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Připojit"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Nahrávám.."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Nadřazená schránka"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr "Vytvořit"
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Odpovědět"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Odpovědět všem"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Možnosti zobrazení"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Povolit odkazy"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Zakákaz odkazy"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Odeslat"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-msgid "Mark as read"
-msgstr "Označit jako přečtené"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-msgid "Mark as unread"
-msgstr "Označit jako nepřečtené"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Vyprázdnit složku"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Upravit vybranou schránku"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Odstranit označené schránky"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Stlačit složku"
-
-#: lib/dbutils.py:36
+"Nahlašte prosím jakékoli objevené problémy nebo vaše návrhy přes\n"
+" emailový "
+"seznam .
\n"
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Zpráva odeslána"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Připojení k databázi %s není nastaveno"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Přístup zamítnut: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Přístup zamítnut"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr "Uložit"
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Neplatný požadavek"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Vložte platné doménové jméno"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Ano"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "Ne"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Nebylo možné změnit heslo: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Bežný uživatel"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super správce"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Správce domény"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Omlouváme se"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "Požadovaná stránka neexistuje."
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Objevila se interní chyba."
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Hledat..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Z adresy"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Předmět"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Obojí"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Chyba:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Nápověda:"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Zavřít"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Předchozí"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Další"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Vítejte v Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Zapamatovat si"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Přihlásit"
diff --git a/modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po b/modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po
index 855fd382a..85ff875e0 100644
--- a/modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po
@@ -1,185 +1,41 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Miroslav Abrahám , 2013,2015
msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2015-01-06 10:05+0000\n"
"Last-Translator: Miroslav Abrahám \n"
-"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/modoboa/language/cs_CZ/)\n"
+"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/"
+"modoboa/language/cs_CZ/)\n"
+"Language: cs_CZ\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: cs_CZ\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Žádný další záznam logu k zobrazení"
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr "Žádná další doména k zobrazení"
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "Nemazat adresář domény"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Tento krok odstraní VŠECHNA data související s touto doménou."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr "Tento krok odstraní VŠECHNA data související s touto doménou, vyjma účtů."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Není určen správce domény"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr "Žádná další identita k zobrazení"
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Nemazat adresář schránky"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr "Žádná další kvóta k zobrazení"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr "Žádná další zpráva k zobrazení"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Odblokovat tento výběr?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Smazat tento výběr?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-msgid "Mark this selection as spam?"
-msgstr "Označit výběr jako spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-msgid "Mark this selection as non-spam?"
-msgstr "Označit výběr jako vyžádané zprávy?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Odblokovat tuto zprávu?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Smazat tuto zprávu?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr "Označit jako spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr "Označit jako vyžádanou zprávu?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Zobrazit úplné záhlaví"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Skrýt záhlaví"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr "Služby aktualizovány"
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr "Žádný další kalendář k zobrazení"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Odstranit tento filtr?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Uložit změny?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Smazat sadu filtrů?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Aktivovat tuto sadu filtrů?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "aktivní"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Vyhledat doménu"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr "Ve schránce není žádná další zpráva."
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Odstranit vybranou schránku?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Schránka odstraněna"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Zpráva odeslána"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "Přesunuji %s zprávu"
-msgstr[1] "Přesunuji %s zprávy"
-msgstr[2] "Přesunuji %s zpráv"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Upozornění"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Zrušit"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr "Interní chyba"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Žádná další informace k zobrazení"
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Hledat"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Hledat..."
diff --git a/modoboa/locale/de/LC_MESSAGES/django.po b/modoboa/locale/de/LC_MESSAGES/django.po
index 5ae5c7e41..35328b0d0 100644
--- a/modoboa/locale/de/LC_MESSAGES/django.po
+++ b/modoboa/locale/de/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2014-12-03 11:02+0000\n"
"Last-Translator: Arvedui \n"
"Language-Team: German (http://www.transifex.com/projects/p/modoboa/language/"
@@ -19,177 +19,129 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Grundsätzlich"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr "Neue Modoboa Version verfügbar"
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Authentifizierung"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Authentifizierungstyp"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Lokal"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Das backend, das zur Authentifizierung genutzt wird"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Standard Passwortschema"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (schwach)"
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (schwach)"
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (schwach)"
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (schwach)"
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (schwach)"
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Verschlüsselungsschema der Mailbox-Passworte"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr "Runden"
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
"Anzahl zu verwendender Runden (nur für sha256crypt und sha512crypt). Zahl "
"muss zwischen 1000 und 999999999 liegen."
-
-#: core/app_settings.py:75
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Geheimer Schlüssel"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Verwendeter Schlüssel, um Passworte zu ver-/entschlüsseln"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "LDAP-Einstellungen"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Server-Adresse"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "Die IP-Adresse des LDAP-Server Hostnamens"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Server-Port"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Der TCP Port des LDAP-Servers"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Gesicherte Verbindung verwenden"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "SSL/TLS-Verbindung für Zugriff auf LDAP-Server verwenden"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Authentifizierungsmethode"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Suchen und Bind anwenden"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Direkter Bind"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Wählen Sie die Authentifizierungsmethode aus"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Bind DN"
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
msgstr ""
"Der DN für einen Bind an den LDAP-Server. Nichts eingeben für anonymen Bind."
-
-#: core/app_settings.py:127
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Bind Passwort"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr "Das Kennwort wenn mit dem Bind DN angemeldet wird."
-
-#: core/app_settings.py:139
+#: core/app_settings.py:134
msgid "Users search base"
msgstr "Anwender Search Base"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "Der DN der Search Base mit der Anwenderkonten gefunden werden"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Suchfilter"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
msgstr ""
"Ein optionaler Filter z.B. (objectClass=person). Das Filter muss "
"entsprechend der LDAP-Konvention in Klammern gesetzt werden."
-
-#: core/app_settings.py:160
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Vorlage für User DN"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
@@ -197,267 +149,180 @@ msgid ""
msgstr ""
"Die Vorlage für einen User DN. Sie sollte einen Platzhalter z.B. %(user)s "
"enthalten."
-
-#: core/app_settings.py:171
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Passwort-Attribut"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Das Attribut für Benutzerpassworte"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Auswählen wenn der LDAP-Server ein Active Directory ist."
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Administrator-Gruppen"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
msgstr ""
"Mitglieder dieser LDAP Posix-Gruppe werden als Domain-Administratoren "
"angelegt werden. Nutzen sie ';', um Gruppen zu separieren."
-
-#: core/app_settings.py:195
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Gruppen Search Base"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "Der DN der Search Base mit Gruppen gefunden werden"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Verschiedenes"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Benachrichtigungs Prüfintervall"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Prüfintervall nach neuen Benachrichtigungen"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Überprüfe auf neue Versionen"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Überprüft automatisch ob eine neuere Version verfügbar ist."
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Maximales Alter eines Log-Eintrags"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "Das maximale Alter eines Log-Eintrags (in Tagen)"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Einträge pro Seite"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Anzahl dargestellter Einträge pro Seite"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Standard Top-Redirect"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr "Die Standardumleitung wenn kein Programm angegeben wurde"
-
-#: core/app_settings.py:268
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Schlüssel muss 16, 24 oder 32 Byte lang sein"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Ungültige Syntax"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Ungültige Zahl für Runden"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Dieses Feld ist erforderlich"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Darstellung"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Bevorzugte Sprache"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Bevorzugte Sprache für Seitendarstellung"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Benutzername"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Passwort"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Altes Passwort"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Neues Passwort"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Bestätigung"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Altes Passwort stimmt nicht überein"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Passwörter stimmen nicht überein"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr "Passwort"
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr "Letzte Anmeldung"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Sie können Ihr eigenes Konto nicht entfernen"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Konnte Kennwort nicht aktualisieren: LDAP-Modul nicht installiert"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "Konto"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Ungültige Zeile"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "Sie können kein Konto einer höheren Rolle importieren"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "Der normale Benutzer '%s' muss eine gültige E-Mail-Adresse besitzen"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr ""
"Die Felder für Benutzername und E-Mail für '%s' dürfen sich nicht "
"unterscheiden"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "aktiviert"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Auswählen, um diese Erweiterung zu aktivieren"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "hinzugefügt"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "verändert"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s der Identität %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "entfernt"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Erweiterungen"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Extension auswählen"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Name"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Version"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Beschreibung"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Speichern"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Information"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Verschiedene Informationen über Modoboa"
-
#: core/templates/core/information.html:5
msgid "An update is available!"
msgstr "Ein Update ist Verfügbar!"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
@@ -471,147 +336,105 @@ msgstr ""
"Modoboa %(version)s steht zum Download bereit. Die liste "
"der Änderungen ist hier "
"verfügbar."
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "ist momentan in Gebrauch."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Aktive Benutzer"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Gruppenname"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Letzte Anmeldung"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Logs"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Vorher auf Modoboa…"
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Datum"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Level"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Nachricht"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Parameter"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Modoboa konfigurieren"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Speichern"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Modoboa-Einstellungen"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Einstellungen"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Einstellungen"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Modoboa anpassen"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Profil"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Aktualisieren sie ihre persönlichen Daten"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Aktualisieren"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Logout"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Parameter gespeichert"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Änderungen übernommen."
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Identität '%s' hat sich erfolgreich angemeldet"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Ihr Benutzername und Passwort stimmen nicht überein. Bitte versuchen Sie es "
"noch einmal."
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Identität '%s' hat sich abgemeldet"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profil aktualisiert"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Einstellungen gespeichert"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Test-Nachrichten"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Virus senden"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Spam senden"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Nachricht gesendet"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -642,2611 +465,98 @@ msgstr ""
"Probleme und Anregungen bitte an die\n"
" Mailingliste berichten.
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Verwaltungskonsole"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Webinterface zur Verwaltung von Domains, Mailkonten und -aliasen"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr "Administration"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Domänen"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Identitäten"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Weiterleiten"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Kann Konto nicht importieren (%s): Die Domain existiert nicht"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "Mailbox %s existiert bereits"
-
-#: extensions/admin/__init__.py:186
-#, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Konto Import fehlgeschlagen (%s): Falscher Kontingentwert"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr "Domain-Alias"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Mailboxen"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Mailbox im Dateisystem verwalten"
-
-#: extensions/admin/app_settings.py:19
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr ""
-"Mailboxen auch in Dateisystem umbenennen oder entfernen wenn sie in Modoboa "
-"umbenannt oder entfernt werden"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Mailbox Besitzer"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr ""
-"UID des virtuellen Benutzers, der Besitzer der Domains, Mailboxen und "
-"Nachrichten im Dateisystem ist."
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr "Standard Domainquota"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr ""
-"Standardquota (in MB) für neu erstelle Domains ohne explizite Wertangabe. "
-"Der Wert 0 bedeutet „Kein Quota“"
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Automatische Konto-Entfernung"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr "Beim Löschen der Mailbox auch das Konto entfernen."
-
-#: extensions/admin/app_settings.py:49
-msgid "Automatic domain/mailbox creation"
-msgstr "Automatische Domain/Mailbox Erstellung"
-
-#: extensions/admin/app_settings.py:52
-msgid "Create a domain and a mailbox when an account is automatically created."
-msgstr ""
-"Erstelle eine Domain und eine Mailbox, wenn ein Account automatisch erstellt "
-"wurde."
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr "Muss eine positive Integer sein"
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr "Ein Mailbox ist erforderlich"
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr ""
-"Der Anwendername. Muss eine gültige E-Mail-Adresse für 'simple users' oder "
-"Administratoren mit einer Mailbox sein."
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Rolle"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Auswählen"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Rechte, die der Benutzer haben wird"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Kennwort bestätigen"
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Aktiviert"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Die angegebenen Kennworte stimmen nicht überein"
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "Sie können Ihr eigenes Konto nicht deaktivieren"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "E-Mail"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Quota"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr ""
-"Quota in MB für diese Mailbox. Geben Sie einen eigenen Wert an oder nutzen "
-"Sie den Standardwert der Domain. Lassen Sie das Feld leer für unbegrenztes "
-"Quota - Domänen-Administratoren ist dies nicht gestattet."
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Aliase"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr ""
-"Alias(e) für diese Mailbox. Geben Sie jeweils nur eine Adresse pro Eingabe "
-"an. Bestätigen Sie mit ENTER um die Eingabe zu bestätigen. Geben Sie '*' an, "
-"um einen 'catchall'-Alias (Bsp: *@example.com) zu erstellen."
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "Domain existiert nicht"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Domain(s)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Domänen, die dieser Anwender administriert"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "E-Mail"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Berechtigungen"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Konto aktualisiert"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Neues Konto"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Konto erstellt"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "E-Mail Adresse"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr ""
-"Adresse einer Verteilerliste. Geben Sie '*' an, um einen 'catchall'-Alias "
-"(Bsp: *@example.com) zu erstellen."
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Empfänger"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr ""
-"Mailboxen auf die der Alias verweist. Geben Sie jeweils nur eine Adresse ein "
-"und bestätigen Sie mit ENTER."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "Der Zugriff auf diese Domain ist ihnen nicht gestattet"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Ungültige Mailbox"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Lokaler Empfänger %s nicht gefunden"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "Empfänger %s existiert bereits"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Keine Empfänger angegeben"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr ""
-"Standardquota in MB für Mailboxen. Bei leerem Feld wird der Domain-Standard "
-"genutzt."
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr ""
-"Alias(e) für diese Mailbox. Geben Sie jeweils nur eine Adresse pro "
-"Eingabefeld an. Bestätigen Sie mit ENTER, um ein neues Eingabefeld zu "
-"erhalten."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr "Ein %s mit diesem Namen existiert bereits"
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr "Domain"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Domänen-Administrator erstellen"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Automatisch Administrator für diese Domain anlegen"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr ""
-"Name des Administrators. Geben Sie nicht den Domainnamen mit an. Er wird "
-"automatisch hinzugefügt."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Aliase erstellen"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Automatisch Standard-Aliase für Domain anlegen"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Ungültiges Format"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "Identität %s existiert bereits"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Domäne verändert"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "optionen"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Neue Domäne"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Domäne erstellt."
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Dateiname"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Separator"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Empfänger"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Geben sie einen oder mehrere, durch Komma ',' separierte Empfänger an"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Lokale Kopien behalten"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr "Nachricht weiterleiten und Kopie in Mailbox ablegen"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr ""
-"Sie können keine Weiterleitung auf ein lokales Ziel anlegen. Bitten Sie "
-"Ihren Administrator stattdessen einen Alias anzulegen."
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Wählen Sie eine Datei"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Bei Fehler fortfahren"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Doppelte Objekte nicht als Fehler behandeln"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Passworte verschlüsseln"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr "Auswählen wenn Kennwörter in Datei nicht verschlüsselt sind"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "Adresse"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just "
-"enter an * character."
-msgstr ""
-"Die Alias-Adresse (ohne den Domain-Anteil). Geben sie für eine Adresse an, "
-"die alles annimmt, * an."
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "Mailboxen"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "Mailbox auf den dieser Alias verweist"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Aliase auf die dieser Alias verweist"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Auswählen um den Alias zu aktivieren"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "Verteilerliste"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "Weiterleitung"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "Alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Ungültige Zeile: %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "Domain '%s' existiert nicht"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "Name"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "Name der Domäne"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Auswählen, um diese Domäne zu aktivieren"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr "Domain"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr "Ungültiger Quota-Wert für Domain '%s'"
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "Der Alias-Name"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "Ziel"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "Domäne auf die dieser Alias verweist"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Unbekannte Domain %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Mailbox-Adresse (ohne den @domain.tld-Anteil)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Konnte Speicherort der Mailbox (%s) nicht bestimmen"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "Das Quota ist größer als das maximale Quota der Domain (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "Ein Quota ist erforderlich"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-msgid "Domain is disabled"
-msgstr "Domain ist deaktiviert"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "MB"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr "Sie können keinen neuen Domänen-Administrator erstellen"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Statistiken"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#, fuzzy
-msgid "Domains and identities"
-msgstr "Identitäten auflisten"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-#, fuzzy
-msgid "Global counters"
-msgstr "Globale Datenbank"
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-#, fuzzy
-msgid "Quantity"
-msgstr "Quarantäne"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Domänen-Aliase"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Tags"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Aktionen"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-#, fuzzy
-msgid "disabled"
-msgstr "aktiviert"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Administratoren"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "Domänen-Administrator fehlt"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Erstellungsdatum"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Datum der letzten Änderung"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Mailboxen-Aliase"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Nachrichten automatisch an andere Adresse weiterleiten"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Name/Empfänger"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Hilfe"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Importiere …"
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Wert auswählen"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Standardwert der Domain verwenden"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Adresse"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Wert"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Limit"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Verwendung (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Suchen"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "aktiviert_m"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "aktiviert_f"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-#, fuzzy
-msgid "List domains"
-msgstr "List-Quotas"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Domain hinzufügen"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Importiere"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Exportiere"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Identitäten auflisten"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "List-Quotas"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Konto hinzufügen"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Alias hinzufügen"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Weiterleitung hinzufügen"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Verteilerliste hinzufügen"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Domain-Identitäten anzeigen"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "%s löschen?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Berechtigung entfernen"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Ein Alias mit diesem Namen existiert bereits"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Erstellen"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Neue Verteilerliste"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Verteilerliste erstellt"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Neuer Alias"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias erstellt"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Neue Weiterleitung"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Weiterleitung erstellt"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Verteilerliste verändert"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Weiterleitung verändert"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Alias verändert"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "Sie können Ihre eigene Domäne nicht löschen"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Domäne gelöscht"
-msgstr[1] "Domänen gelöscht"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Identitäten exportieren"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Domains exportieren"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Ungültige Anfrage"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Konto gelöscht"
-msgstr[1] "Konten gelöscht"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-"Verwenden sie eine CSV-Datei mit einem der folgenden Formate:\n"
-"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
-" \n"
-"Das erste Element jeder Zeile ist zwingend und muss gleich zum "
-"vorhergehenden sein.
\n"
-"Ein anderes Zeichen als Trenner ist gestattet.
\n"
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Domains importieren"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "Objekt existiert bereits: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d Objekte erfolgreich importiert"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; "
-"address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-"Verwenden sie eine CSV-Datei in einem der folgenden Formate:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; "
-"address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"Das erste Element einer Zeile ist zwingend und muss gleich mit einem der "
-"vorhergehenden sein.
\n"
-"\n"
-"Ein anderes Zeichen als Separator ist gestattet.
\n"
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Identitäten importieren"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Weiterleitung aktualisiert"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Einfache amavis Management Oberfläche"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Quarantäne"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Quarantäne-Einstellungen"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Maximales Alter einer Nachricht"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr ""
-"Maximales Alter (in Tagen) von Nachrichten in der Quarantäne bevor sie "
-"gelöscht werden"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Nachrichten freigegeben"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Freigegebene Nachrichten entfernen"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr "Freigegebene Nachrichten löschen wenn Datenbank bereinigt wird"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Verbindungsmodus für Amavis"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Modus für Zugriff auf den PDP-Server"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "PDP-Server Adresse"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "PDP-Server addresse (im inet-Modus)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "PDP-Server-Port"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "PDP-Server port (im inet-Modus)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "PDP-Server Socket"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Pfad zum PDP-Server Socket (im UNIX-Modus)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Anwender dürfen Nachrichten in Quarantäne selber freigeben"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Anwender dürfen Nachrichten in Quarantäne selber freigeben"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "'Self-Service'-Modus aktivieren"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "'Self-Service'-Modus aktivieren"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Absender von Benachrichtigungen"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr ""
-"Die Mailadresse, die verwendet wird, um Benachrichtigungen zu versenden"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr "Manuelles lernen"
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr "Aktiviere manuelles lernen"
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr "Erlaube Super-Administratoren Spamassassin manuell zu trainieren."
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr "Ist Spamassassin lokal?"
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr "Stelle ein ob Spamassassin auf dem selben Server läuft wie modoboa"
-
-#: extensions/amavis/app_settings.py:99
-msgid "Default user"
-msgstr "Standard User"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr "Nenne der Besitzer der bayesschen Datenbank"
-
-#: extensions/amavis/app_settings.py:107
-msgid "Spamd address"
-msgstr "Spamd Adresse"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr "Die IP-Adresse unter der spamd erreicht werden kann."
-
-#: extensions/amavis/app_settings.py:113
-msgid "Spamd port"
-msgstr "Spamd Port"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr "Der TCP Port an dem spamd lauscht."
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr "Aktiviere manuelles lernen pro Domain."
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr ""
-"Erlaubt Domainadministratoren Spamassassin zu trainieren (mit dedizierter "
-"Datenbank für jede Domain)"
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr "Aktiviere manuelles lernen für normale User"
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr ""
-"Erlaube normalen Usern Spamassassin zu trainieren (mit dedizierter Datenbank "
-"für jeden User)"
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Anzahl dargestellter Nachrichten pro Seite"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr ""
-"Legt die maximale Anzahl von Nachrichten fest, die in einer Seite "
-"dargestellt werden"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr "Globale Datenbank"
-
-#: extensions/amavis/forms.py:94
-msgid "Domain's database"
-msgstr "Domänen Datenbank"
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr "Benutzer Datenbank"
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr "Offene Anfragen"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Inhaltsfilter"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "Verbindung zu amavis fehlgeschlagen: %s"
-
-#: extensions/amavis/lib.py:131
-msgid "No recipient found"
-msgstr "Kein Empfänger gefunden."
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Virusfilter"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "Ja"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "Nein"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "Standard"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Virus-Prüfungen umgehen oder nicht. Geben Sie, um den Domain-Standard zu "
-"nutzen, keinen individuellen Wert an."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "SPAM-Filter"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Spam-Prüfungen umgehen oder nicht. Geben Sie, um den Domain-Standard zu "
-"nutzen, keinen individuellen Wert an."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Filter für unerwünschte Dateien"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Unerwünschte Dateien umgehen oder nicht. Geben Sie, um den Domain-Standard "
-"zu nutzen, keinen individuellen Wert an."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "SPAM-Markierung"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global "
-"settings."
-msgstr ""
-"Betreff:-Zeile einer Spam-Nachricht mit dem angegebenen Text ergänzen. "
-"Wählen Sie 'Standard' für den systemweiten Standard."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Quarantäne leeren"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Nachricht gelöscht"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d Nachricht erfolgreich gelöscht"
-msgstr[1] "%(count)d Nachrichten erfolgreich gelöscht"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Anfrage gesendet"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Nachricht freigegeben"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d Anfrage gesendet"
-msgstr[1] "%(count)d Anfragen gesendet"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d Nachicht erfolgreich freigegeben"
-msgstr[1] "%(count)d Nachichten erfolgreich freigegeben"
-
-#: extensions/amavis/views.py:360
-#, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d Nachricht erfolgreich verarbeitet."
-msgstr[1] "%(count)d Nachrichten erfolgreich verarbeitet."
-
-#: extensions/amavis/views.py:394
-msgid "Select a database"
-msgstr "Wähle eine Datenbank"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr "Bestätigen"
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Offene Freigabeanfragen"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Schwellwerte"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "oder mehr ist SPAM"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "oder mehr soll SPAM-Nachricht verwerfen"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr "Punktzahl"
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "An"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "Von"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Betreff"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-msgid "Released"
-msgstr "Freigegeben"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-msgid "Marked as spam"
-msgstr "Als Spam markiert"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-msgid "Marked as non-spam"
-msgstr "Als kein Spam Markiert"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Quarantäne-Management"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr "Auswählen"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr "Säubern"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr "Fehlerhafte Header"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Schlechtes MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr "Unerwünschte Dateien"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Freigeben"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Löschen"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-msgid "Mark as spam"
-msgstr "Als Spam markieren."
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr "Als kein Spam markieren."
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Alle Nachrichten"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr "Alle"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr "Nur Säubern"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr "Nur Spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr "Nur Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr "Nur Fehlerhafte Header"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr "Nur Fehlerhaftes MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr "Nur Unerwünschte Dateien"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] ""
-"\n"
-"%(counter)s Freigabe-Anforderung wartet auf sie.\n"
-msgstr[1] ""
-"\n"
-"%(counter)s Freigabe-Anforderungen warten auf sie.\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Skizze:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "Von:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "An:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Datum:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Betreff:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Rektion auf diese Nachricht:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr ""
-"Bitte besuchen sie %(listingurl)s um eine vollständige Ausgabe zu erhalten."
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Zurück"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Alle Mail-Header ansehen"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr ""
-"Administrator-Ressourcen, um die Anzahl erstellbarer Objekte einzuschränken"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Grenzwerte"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Standard-Grenzwerte"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Domänen-Administratoren"
-
-#: extensions/limits/app_settings.py:15
-msgid "Maximum number of allowed domain administrators for a new administrator"
-msgstr ""
-"Maximale Anzahl Domänenadministratoren, die ein neuer Administrator "
-"erstellen darf"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Maximale Anzahl Domains, die ein neuer Administrator erstellen darf"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr ""
-"Maximale Anzahl Domain Aliase, die ein neuer Administrator erstellen darf"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Maximale Anzahl Mailboxen, die ein neuer Administrator erstellen darf"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Maximale Anzahl Aliase, die ein neuer Administrator erstellen darf"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Ungültiger Grenzwert"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Ihre Ressourcen wurde noch nicht initialisiert"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr ""
-"Sie verfügen nicht über ausreichend Rechte, um unbegrenzte Werte anzugeben"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Reseller"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Ressourcen"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s: Grenze erreicht"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Nicht ausreichend Ressourcen"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr "Maximale Anzahl Domains, die ein Administrator erstellen darf"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Maximale Anzahl Domains, die dieser Anwender erstellen darf"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Maximale Anzahl Domain Aliase, die dieser Anwender erstellen darf"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Maximale Anzahl Mailboxen, die dieser Anwender erstellen darf"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr "Maximale Anzahl Mailbox-Aliase, die dieser Anwender erstellen darf"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "unbestimmt"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "unbegrenzt"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Ressourcen-Verbrauch"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr ""
-"Automatische Antwort (Abwesenheitsbenachrichtigung) über Postfix-Programm"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Automatische Antworten"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Zeitüberschreitung für automatische Antworten"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr ""
-"Zeit in Sekunden zwischen zwei automatisierten Antworten an denselben "
-"Empfänger"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr "Standard-Betreff"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr "Ich bin weg"
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr "Standardbetreff wenn eine Antwortnachricht automatisch generiert wird"
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr "Standard-Inhalt"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr ""
-"Ich bin im Moment weg und werde antworten sobald ich zurück bin.\n"
-"\n"
-"Mit freundlichen Grüßen\n"
-"%(name)s\n"
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr ""
-"Standardinhalt wenn eine Antwort automatisch erstellt wird. Das '%(name)s' "
-"Makro wird gegen den vollen Anwendernamen ersetzt."
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr "Automatisierte Antwort beginnend mit diesem Datum aktivieren"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Bis"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Aktivieren Sie ihre automatisierte Antwort bis zu diesem Datum"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Das Datum ist vorbei"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr "Muss größer als Wert des Startdatums sein"
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Automatische Antwort"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr "Automatische Antwort aktivieren"
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr "Automatische Postfix-Antwort (de)aktivieren"
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "Betreff"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "Der Betreff, der in den versendeten Nachrichten verwendet wird"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "Inhalt"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "Der Inhalt, der in den versendeten Nachrichten verwendet wird"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Aktivieren/Deaktivieren Sie die automatisierte Antwort"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Automatische Antwort erfolgreich aktualisiert."
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr ""
-"Gegen sie eine Nachricht an, die gesendet werden soll, wenn Sie nicht "
-"erreichbar sind"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr "Relaydomain-Unterstützung für Postfix"
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr "Relaydomain"
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr "Pfad zu Postfix master.cf-Datei"
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr "Pfad zur master.cf Konfigurationsdatei"
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr ""
-"Alias(e) für diese Relaydomain. Geben Sie jeweils nur einen pro Eingabefeld "
-"an. Bestätigen Sie mit ENTER, um ein weiteres Eingabefeld zu erhalten."
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr "Relaydomain-Alias"
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr "Relaydomain"
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr "Relaydomain geändert"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr "Relaydomain hinzufügen"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr "Maximale Anzahl Relaydomains, die dieser Anwender erstellen darf"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr "Relaydomain-Aliase"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr "Maximale Anzahl Relaydomain-Aliase, die dieser Anwender erstellen darf"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients"
-"em> \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients"
-"em> \n"
-"relaydomainalias; name; target; enabled \n"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr ""
-"Maximale Anzahl Relaydomains, die ein neuer Administrator erstellen darf"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr ""
-"Maximale Anzahl Relaydomain-Aliase, die ein neuer Administrator erstellen "
-"darf"
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr "Der 'service'-Name"
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr "Ziel-Host"
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr "Entfernte Destination für diese Domain"
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr "Empfänger verifizieren"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr "Auf gültige Empfänger prüfen"
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr "Relaydomain"
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr "Die Relaydomain auf die dieser Alias verweist"
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr "Relaydomain '%s' existiert nicht"
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr "Relaydomain erstellt"
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr "Neue Relaydomain"
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr "Relaydomain gelöscht"
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr "Scanne"
-
-#: extensions/radicale/__init__.py:34
-msgid "Radicale management"
-msgstr "Radicale Verwaltung"
-
-#: extensions/radicale/__init__.py:38
-msgid "Management frontend for Radicale, a simple calendar and contact server."
-msgstr ""
-"Verwaltungsoberfläche für Radicle, ein simpler Kalender- und Kontaktserver."
-
-#: extensions/radicale/app_settings.py:11
-msgid "Server settings"
-msgstr "Server Einstellungen"
-
-#: extensions/radicale/app_settings.py:15
-msgid "Server URL"
-msgstr "Server URL"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr ""
-"Die URL deines Radivale Servers. Sie wird Benutzt um Kalender URLs zu "
-"erstellen."
-
-#: extensions/radicale/app_settings.py:24
-msgid "Rights management"
-msgstr "Rechte Verwaltung"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr "Pfad zur Rechtedatei"
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr "Pfad zur der Datei, die die Rechtedefinition enthält."
-
-#: extensions/radicale/app_settings.py:36
-msgid "Allow calendars administration"
-msgstr "Erlaube Kalender Administration"
-
-#: extensions/radicale/app_settings.py:39
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr ""
-"Erlaube Domain-Administratoren Benutzer Kalender zu verwalten.(Lesend und "
-"schreibend)"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr "Lesen"
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr "Schreiben"
-
-#: extensions/radicale/forms.py:134
-#, python-format
-msgid "Mailbox %s does not exist"
-msgstr "Mailbox %s existiert nicht"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr "Rechte"
-
-#: extensions/radicale/forms.py:162
-msgid "New calendar"
-msgstr "Neues Kalender"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-msgid "Calendar created"
-msgstr "Kalender erstellt"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-msgid "Calendar updated"
-msgstr "Kalender aktualisiert"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr "Kalender"
-
-#: extensions/radicale/models.py:94
-msgid "User"
-msgstr "Benutzer"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr "Geteilt"
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-msgid "Calendar removed"
-msgstr "Kalender entfernt"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr "Neuer geteilter Kalender"
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr "Abschicken"
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr "Nutze die Folgende Adresse um auf dem Kalender zuzugreifen: "
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr "Besitzer"
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-msgid "Add calendar"
-msgstr "Kalender hinzufügen"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr "Geteilten Kalender hinzufügen"
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr "Kalender Details ansehen"
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr "Bearbeite %s"
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Plugin, um auf einfache Weise server-seitige Filter zu erstellen"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "SIEVE-Filter"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Nachrichten-Filter"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "ManageSieve-Einstellungen"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Adresse Ihres MANAGESIEVE-Servers"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "TCP-Port auf Ihr MANAGESIEVE-Server lauscht"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "STARTTLS für Verbindungsaufbau nutzen"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "STARTTLS benutzen"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Authentifizierungsmechanismus"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Bevorzugte Authentifizierungsmethode"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Editor-Modus"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Wählen Sie den Modus aus in dem der Editor arbeiten soll"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Häckchen setzen, damit Filter aktiv wird"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Alle folgende"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Irgendeines der folgenden"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "enthält"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "enthält nicht"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "ist"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "ist nicht"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Sender"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Empfänger"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Cc"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Größe"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "ist größer als"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "ist weniger als"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Verschiebe Nachricht nach"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Leite Nachricht um zu"
-
-#: extensions/sievefilters/forms.py:110
-msgid "Wrong filter name"
-msgstr "Falscher Filtername"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr ""
-"Verbindung zu MANAGESIEVE-Server fehlgeschlagen. Überprüfen Sie Ihre "
-"Konfiguration."
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Kein weiterer Platz auf Server verfügbar"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Konnte Filter-Satz nicht laden"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Neuer Filter"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filter erstellt"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Filter bearbeiten"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filter verändert"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filter entfernt"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Konnte Filter nicht entfernen"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Filter-Satz gespeichert"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Filter erstellt"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Neuen Filter-Satz erstellen"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Filter entfernt"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Filter-Satz aktiviert"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Bedingungen"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Aktiv"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Noch keine Filter definiert"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Filter-Sätze"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "aktiv"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr ""
-"Nich keine Filter-Sätze definiert. Sie müssen einen erstellen, damit sie "
-"Filter erstellen können."
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Neuer Filter-Satz"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Filter-Satz speichern"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Filter-Satz aktivieren"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Filter-Satz entfernen"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Herunterladen"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Filter entfernen"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Filter nach oben verschieben"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Filter nach unten verschieben"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Grafische E-Mail-Statistik (setzt RRDtool ein)"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Grafische Statistiken"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Pfad zur Log-Datei"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Pfad zur Log-Datei, um Statistiken zu sammeln"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Ablageverzeichnis für RRD-Dateien"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Pfad zum Verzeichnis in dem die RRD-Dateien abgelegt werden"
-
-#: extensions/stats/graphics.py:98
-msgid "Average traffic (msgs/min)"
-msgstr "Durchschnittlicher Traffic (nachrichten/min)"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "Gesendete Nachrichten"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "Empfangene Nachrichten"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "Zurückgeworfene Nachrichten"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "Abgewiesene Nachrichten"
-
-#: extensions/stats/graphics.py:112
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Durchschnittliche Traffic menge (bytes/min)"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "Empfangsgrösse"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "Versendegrösse"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Mailverkehr"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Keine Statistik-Daten verfügbar"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Tag"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Woche"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Monat"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Jahr"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr "Benutzerdefiniert"
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Unbekanntes graphisches Set"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Ungültiger individueller Zeitraum"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Domain suchen"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Antworten"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Einfaches IMAP-Webmail"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Maximale Anhang-Grösse"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Maximale Größe Anhang in Bytes (oder KB, MB, GB wenn angegeben)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "IMAP-Einstellungen"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Addresse Ihres IMAP-Servers"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Gesicherte Verbindung für Zugriff auf IMAP-Server verwenden"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Port auf dem der IMAP-Server lauscht"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "SMTP-Einstellungen"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Addresse Ihres SMTP-Servers"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Gesicherter Verbindungsaufbau"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Kein"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Gesicherte Verbindung für Zugriff auf SMTP-Server verwenden"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Port auf dem der SMTP-Server lauscht"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Anmeldung erforderlich"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "Server erfordert Authentifizierung"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Standard Betrachtungsmodus für Nachrichten"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "Der Standard Modus zum Betrachten einer Nachricht"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Aktiviere Darstellung von HTML-Links"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Aktiviere/Deaktiviere Darstellung von HTML-Links"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr ""
-"Legt die maximale Anzahl von Nachrichten fest, die in einer Seite "
-"dargestellt werden"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Aktualisierungsintervall für Liste"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Aktualisierungsintervall für Ordner (in Sekunden)"
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr "Breite des Mailboxcontainers"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr "Die Breite der Mailbox-Liste"
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Papierkorb"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Ordner für gelöschte Nachrichten"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Gesendete Nachrichten"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Ordner für Gesendete Nachrichten"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Entwürfe"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Ordner für Entwürfe"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Nachrichten erstellen"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Standard-Editor"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "Der Standard-Editor zum Erstellen einer Nachricht"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Signatur"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Benutzerdefinierte E-Mail-Signatur"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr "Wert muss eine positive Integer sein (>0)"
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Server-Antwort"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Unbekannte Aktion"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "Cci"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Webmail"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d Nachricht gelöscht"
-msgstr[1] "%(count)d Nachrichten gelöscht"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Mailbox leer"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Mailbox erstellt."
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Neue Mailbox erstellen"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Mailbox bearbeiten"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Mailbox aktualisiert"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Konnte Anhang nicht speichern"
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "Anhang ist zu groß (Limit: %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Dateianhänge"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Fehlerhafte Anfrage"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Konnte Anhang nicht entfernen:"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Unbekannter Anhang"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "schrieb:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Gesendete Nachrichten"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Konnte Trenner für Hierarchie nicht in Erfahrung bringen"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "Verbindung zu IMAP-Server fehlgeschlagen: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Anhängen"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Lade hoch …"
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Eltern-Mailbox"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr "Verfassen"
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Antworten"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Allen Antworten"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Optionen darstellen"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Links aktivieren"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Links aktivieren"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Senden"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-msgid "Mark as read"
-msgstr "Als gelesen markieren"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-msgid "Mark as unread"
-msgstr "Als ungelesen markieren"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Leerer Ordner"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Ausgewählte Mailbox bearbeiten"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Markierte Mailbox entfernen"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Ordner komprimieren"
-
-#: lib/dbutils.py:36
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Nachricht gesendet"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Verbindung zu Datenbank %s nicht konfiguriert"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Erlaubnis verweigert: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Berechtigung verweigert"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr "Abschicken"
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Ungültige Anfrage"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Geben Sie einen gültigen Domain-Namen an"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Ja"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "Nein"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Konnte Kennwort nicht aktualisieren: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Normaler Anwender"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super-Administrator"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Domänen-Administrator"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Entschuldigung"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "Die angeforderte Seite existiert nicht"
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Ein interne Fehler ist aufgetreten"
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Suchen..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "From:-Adresse"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Betreff"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Beide"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Fehler:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Hilfe:"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Schliessen"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Vorheriges"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Nächstes"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Willkommen zu Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Erinnere mich"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Anmelden"
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
diff --git a/modoboa/locale/de/LC_MESSAGES/djangojs.po b/modoboa/locale/de/LC_MESSAGES/djangojs.po
index 1fe2e3f4b..bb99e0e0e 100644
--- a/modoboa/locale/de/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/de/LC_MESSAGES/djangojs.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Arvedui , 2014
# Patrick Koetter , 2010
@@ -9,177 +9,34 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2014-12-01 12:12+0000\n"
"Last-Translator: Arvedui \n"
-"Language-Team: German (http://www.transifex.com/projects/p/modoboa/language/de/)\n"
+"Language-Team: German (http://www.transifex.com/projects/p/modoboa/language/"
+"de/)\n"
+"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Keine weiteren log eintrage"
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr "Keine weiteren Domains"
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "Verzeichnis der Domain nicht löschen"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Diese Aktion wird ALLE mit der Domain verbundenen Daten löschen."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr "Diese Aktion wird ALLE mit der Domain verbundenen Daten löschen - ausser Mailkonten."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Domain-Administrator fehlt"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr "Keine weiteren Identitäten"
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Verzeichnis der Mailbox nicht löschen"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr "Keine weiteren Quotas"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr "Keine weiteren Nachrichten"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Diese Auswahl freilassen?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Diese Auswahl löschen?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-msgid "Mark this selection as spam?"
-msgstr "Diese Auswahl als Spam markieren?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-msgid "Mark this selection as non-spam?"
-msgstr "Diese Auswahl als kein Spam markieren?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Diese Nachricht freilassen?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Diese Nachricht löschen?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr "Als Spam markieren?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr "Als kein Spam markieren?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Vollansicht Header anzeigen"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Vollansicht Header ausblenden"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr "'service'-Liste aktualisiert"
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr "Keine weiteren Kalender"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Diesen Filter entfernen?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Änderungen speichern?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Diesen Filter entfernen?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Diesen Filter aktivieren?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "aktiv"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Domain suchen"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr "Keine weiteren Nachrichten in der Mailbox."
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Ausgewählte Mailbox entfernen?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Mailbox entfernt"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Nachricht gesendet"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "Verschiebe %s Nachricht"
-msgstr[1] "Verschiebe %s Nachrichten"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Warnung"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Abbrechen"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr "Interner Fehler"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Keine weiteren Einträge"
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Suche"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Suchen..."
diff --git a/modoboa/locale/en/LC_MESSAGES/django.po b/modoboa/locale/en/LC_MESSAGES/django.po
index 67b20d79c..4419e2e77 100644
--- a/modoboa/locale/en/LC_MESSAGES/django.po
+++ b/modoboa/locale/en/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -16,434 +16,297 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr ""
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr ""
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr ""
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr ""
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr ""
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr ""
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr ""
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr ""
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr ""
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr ""
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr ""
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr ""
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr ""
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr ""
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
-
-#: core/app_settings.py:75
+#: core/app_settings.py:70
msgid "Secret key"
msgstr ""
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr ""
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr ""
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr ""
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr ""
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr ""
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr ""
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr ""
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr ""
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr ""
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr ""
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr ""
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr ""
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr ""
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
msgstr ""
-
-#: core/app_settings.py:127
+#: core/app_settings.py:122
msgid "Bind password"
msgstr ""
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
-
-#: core/app_settings.py:139
+#: core/app_settings.py:134
msgid "Users search base"
msgstr ""
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr ""
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr ""
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
msgstr ""
-
-#: core/app_settings.py:160
+#: core/app_settings.py:155
msgid "User DN template"
msgstr ""
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
"placeholder (ie. %(user)s)"
msgstr ""
-
-#: core/app_settings.py:171
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr ""
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr ""
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr ""
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr ""
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr ""
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
msgstr ""
-
-#: core/app_settings.py:195
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr ""
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr ""
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr ""
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr ""
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr ""
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
msgid "Check new versions"
msgstr ""
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr ""
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr ""
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr ""
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr ""
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr ""
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr ""
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
-
-#: core/app_settings.py:268
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr ""
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr ""
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr ""
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr ""
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr ""
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr ""
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr ""
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr ""
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr ""
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr ""
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr ""
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr ""
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr ""
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr ""
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr ""
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr ""
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr ""
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr ""
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr ""
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr ""
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr ""
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr ""
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr ""
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr ""
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr ""
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr ""
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr ""
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr ""
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr ""
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr ""
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+msgid "The extension(s) you are using"
msgstr ""
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr ""
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr ""
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr ""
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr ""
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr ""
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr ""
-
#: core/templates/core/information.html:5
msgid "An update is available!"
msgstr ""
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
@@ -453,145 +316,103 @@ msgid ""
"\">here.\n"
" "
msgstr ""
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr ""
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr ""
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr ""
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr ""
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr ""
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr ""
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr ""
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr ""
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr ""
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr ""
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr ""
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr ""
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr ""
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr ""
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr ""
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr ""
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr ""
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr ""
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr ""
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr ""
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr ""
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr ""
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr ""
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr ""
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr ""
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr ""
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr ""
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr ""
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr ""
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr ""
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr ""
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr ""
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -608,2496 +429,93 @@ msgid ""
" the "
"mailing list .
\n"
msgstr ""
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
msgstr ""
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr ""
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr ""
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr ""
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr ""
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr ""
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr ""
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr ""
-
-#: extensions/admin/__init__.py:186
-#, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr ""
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr ""
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr ""
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr ""
-
-#: extensions/admin/app_settings.py:19
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr ""
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr ""
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr ""
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr ""
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr ""
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr ""
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr ""
-
-#: extensions/admin/app_settings.py:49
-msgid "Automatic domain/mailbox creation"
-msgstr ""
-
-#: extensions/admin/app_settings.py:52
-msgid "Create a domain and a mailbox when an account is automatically created."
-msgstr ""
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr ""
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr ""
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr ""
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr ""
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr ""
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr ""
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr ""
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr ""
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr ""
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr ""
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr ""
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr ""
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr ""
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr ""
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr ""
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr ""
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr ""
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr ""
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr ""
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr ""
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr ""
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr ""
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr ""
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr ""
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr ""
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr ""
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr ""
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr ""
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr ""
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr ""
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr ""
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr ""
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr ""
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr ""
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr ""
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr ""
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr ""
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr ""
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr ""
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr ""
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr ""
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr ""
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr ""
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr ""
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr ""
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr ""
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr ""
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr ""
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just "
-"enter an * character."
-msgstr ""
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr ""
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr ""
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr ""
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr ""
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr ""
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr ""
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr ""
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr ""
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr ""
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr ""
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr ""
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr ""
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr ""
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr ""
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr ""
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr ""
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr ""
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr ""
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr ""
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr ""
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr ""
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr ""
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-msgid "Domain is disabled"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-msgid "Domains and identities"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-msgid "Quantity"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr ""
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr ""
-
-#: extensions/admin/templates/admin/domains_table.html:4
-msgid "disabled"
-msgstr ""
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr ""
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr ""
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr ""
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr ""
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr ""
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr ""
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr ""
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr ""
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr ""
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr ""
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr ""
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr ""
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr ""
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr ""
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr ""
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:38
-msgid "List domains"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr ""
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr ""
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr ""
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr ""
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr ""
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr ""
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr ""
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr ""
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr ""
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr ""
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr ""
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr ""
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr ""
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr ""
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] ""
-msgstr[1] ""
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr ""
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr ""
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr ""
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] ""
-msgstr[1] ""
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr ""
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr ""
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr ""
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; "
-"address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr ""
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr ""
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr ""
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:99
-msgid "Default user"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:107
-msgid "Spamd address"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:113
-msgid "Spamd port"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr ""
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr ""
-
-#: extensions/amavis/forms.py:94
-msgid "Domain's database"
-msgstr ""
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr ""
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr ""
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr ""
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr ""
-
-#: extensions/amavis/lib.py:131
-msgid "No recipient found"
-msgstr ""
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr ""
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr ""
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr ""
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr ""
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr ""
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr ""
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr ""
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr ""
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr ""
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr ""
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global "
-"settings."
-msgstr ""
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr ""
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr ""
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] ""
-msgstr[1] ""
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr ""
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr ""
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] ""
-msgstr[1] ""
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] ""
-msgstr[1] ""
-
-#: extensions/amavis/views.py:360
-#, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] ""
-msgstr[1] ""
-
-#: extensions/amavis/views.py:394
-msgid "Select a database"
-msgstr ""
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr ""
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-msgid "Released"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-msgid "Marked as spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-msgid "Marked as non-spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-msgid "Mark as spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] ""
-msgstr[1] ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr ""
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr ""
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr ""
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr ""
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr ""
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr ""
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr ""
-
-#: extensions/limits/app_settings.py:15
-msgid "Maximum number of allowed domain administrators for a new administrator"
-msgstr ""
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr ""
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr ""
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr ""
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr ""
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr ""
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr ""
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr ""
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr ""
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr ""
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr ""
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr ""
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr ""
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr ""
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr ""
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr ""
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr ""
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr ""
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr ""
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr ""
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr ""
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr ""
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr ""
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr ""
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr ""
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr ""
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr ""
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr ""
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr ""
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr ""
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr ""
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr ""
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr ""
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr ""
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr ""
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients"
-"em> \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr ""
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr ""
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr ""
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr ""
-
-#: extensions/radicale/__init__.py:34
-msgid "Radicale management"
-msgstr ""
-
-#: extensions/radicale/__init__.py:38
-msgid "Management frontend for Radicale, a simple calendar and contact server."
-msgstr ""
-
-#: extensions/radicale/app_settings.py:11
-msgid "Server settings"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:15
-msgid "Server URL"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr ""
-
-#: extensions/radicale/app_settings.py:24
-msgid "Rights management"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:36
-msgid "Allow calendars administration"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:39
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr ""
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr ""
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr ""
-
-#: extensions/radicale/forms.py:134
-#, python-format
-msgid "Mailbox %s does not exist"
-msgstr ""
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr ""
-
-#: extensions/radicale/forms.py:162
-msgid "New calendar"
-msgstr ""
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-msgid "Calendar created"
-msgstr ""
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-msgid "Calendar updated"
-msgstr ""
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr ""
-
-#: extensions/radicale/models.py:94
-msgid "User"
-msgstr ""
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr ""
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-msgid "Calendar removed"
-msgstr ""
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr ""
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr ""
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr ""
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-msgid "Add calendar"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr ""
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr ""
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr ""
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr ""
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr ""
-
-#: extensions/sievefilters/forms.py:110
-msgid "Wrong filter name"
-msgstr ""
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr ""
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr ""
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr ""
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr ""
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr ""
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr ""
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr ""
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr ""
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr ""
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr ""
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr ""
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr ""
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr ""
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr ""
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr ""
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr ""
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr ""
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr ""
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr ""
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr ""
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr ""
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr ""
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr ""
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr ""
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr ""
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr ""
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr ""
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr ""
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr ""
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr ""
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr ""
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr ""
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr ""
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr ""
-
-#: extensions/stats/graphics.py:98
-msgid "Average traffic (msgs/min)"
-msgstr ""
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr ""
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr ""
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr ""
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr ""
-
-#: extensions/stats/graphics.py:112
-msgid "Average normal traffic size (bytes/min)"
-msgstr ""
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr ""
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr ""
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr ""
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr ""
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr ""
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr ""
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr ""
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr ""
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr ""
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr ""
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr ""
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr ""
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr ""
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr ""
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr ""
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr ""
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr ""
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr ""
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] ""
-msgstr[1] ""
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr ""
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr ""
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr ""
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr ""
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr ""
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr ""
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr ""
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr ""
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr ""
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr ""
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr ""
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr ""
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr ""
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr ""
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr ""
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr ""
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr ""
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr ""
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-msgid "Mark as read"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-msgid "Mark as unread"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr ""
-
-#: lib/dbutils.py:36
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr ""
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr ""
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr ""
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr ""
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr ""
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr ""
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr ""
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr ""
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr ""
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr ""
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr ""
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr ""
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr ""
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr ""
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr ""
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr ""
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr ""
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr ""
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr ""
-
#: templates/common/error.html:4
msgid "Error:"
msgstr ""
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr ""
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr ""
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr ""
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr ""
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr ""
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr ""
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr ""
diff --git a/modoboa/locale/en/LC_MESSAGES/djangojs.po b/modoboa/locale/en/LC_MESSAGES/djangojs.po
index cebe8d25a..cfcd3c47e 100644
--- a/modoboa/locale/en/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/en/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -16,168 +16,24 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-msgid "Mark this selection as spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-msgid "Mark this selection as non-spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr ""
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr ""
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr ""
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr ""
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr ""
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr ""
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr ""
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr ""
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr ""
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr ""
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr ""
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr ""
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr ""
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] ""
-msgstr[1] ""
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr ""
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr ""
-
#: static/js/global.js:329
msgid "Internal error"
msgstr ""
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr ""
-
#: static/js/listing.js:46
msgid "Search"
msgstr ""
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr ""
diff --git a/modoboa/locale/es/LC_MESSAGES/django.po b/modoboa/locale/es/LC_MESSAGES/django.po
index d42548981..c639410e3 100644
--- a/modoboa/locale/es/LC_MESSAGES/django.po
+++ b/modoboa/locale/es/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2013-10-01 09:56+0000\n"
"Last-Translator: Pedro Gracia \n"
"Language-Team: Spanish (http://www.transifex.com/projects/p/modoboa/language/"
@@ -19,179 +19,131 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "General"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr ""
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autenticación"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Tipo de autenticación"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Local"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "El sistema usado para autenticación"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Esquema de contraseña por defecto"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr ""
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr ""
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr ""
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr ""
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr ""
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Esquema usado para cifrar las contraseñas del mailbox"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr ""
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
-
-#: core/app_settings.py:75
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Clave secreta"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Clave usada para cifrar/descifrar contraseñas"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Configuración de LDAP"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Dirección del servidor"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "La dirección IP del servidor de nombres (DNS) del servidor LDAP"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Puerto del servidor"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Número de puerto TCP usado por el servidor LDAP"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Usa una conexión segura"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Usa una conexión SSL/TLS para acceder al servidor LDAP"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Método de autenticación"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Buscar y unir"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Unión directa"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Elegir el método de autenticación a usar"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Unir a DN"
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
msgstr ""
"El nombre distinguido a usar cuando nos unimos al servidor LDAP. Dejar vació "
"para una unión anónima"
-
-#: core/app_settings.py:127
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Unir contraseña"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"La contraseña a usar cuando nos unimos al servidor LDAP (con 'Unir a DN')"
-
-#: core/app_settings.py:139
+#: core/app_settings.py:134
#, fuzzy
msgid "Users search base"
msgstr "Buscar base"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
#, fuzzy
msgid "The distinguished name of the search base used to find users"
msgstr "El nombre disgituido de la búsqueda base"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtro de búsqueda"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
msgstr ""
"Una cadena de filtro opcional (p.e. '(objectClass=person)'). Para que sea "
"válido tiene que ser encerrado entre paréntesis."
-
-#: core/app_settings.py:160
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Plantilla DN del usuario"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
@@ -199,275 +151,188 @@ msgid ""
msgstr ""
"La plantilla usada para contriunr un DN de usuario. Debería contener una "
"cadena reemplazables (p.e. %(user)s)"
-
-#: core/app_settings.py:171
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Atributo de la contraseña"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "El atributo usado para guardar las contraseñas del usuario"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Directorio Activo"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Decir si el servidor de LDAP es uno del tipo Directorio Activo"
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
#, fuzzy
msgid "Administrator groups"
msgstr "Administradores"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
msgstr ""
-
-#: core/app_settings.py:195
+#: core/app_settings.py:190
#, fuzzy
msgid "Groups search base"
msgstr "Buscar base"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
#, fuzzy
msgid "The distinguished name of the search base used to find groups"
msgstr "El nombre disgituido de la búsqueda base"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Otros"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
#, fuzzy
msgid "Top notifications check interval"
msgstr "Notificaciones al remitente"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
#, fuzzy
msgid "Interval between two top notification checks"
msgstr "Intervalo entre dos peticiones de chequeo"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
#, fuzzy
msgid "Check new versions"
msgstr "Marcar para activar esta extensión"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr ""
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Máximo tiempo de almacenamiento del log"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "El tiempo máximo de almacenamiento del log en días"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Items por página"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Número de elementos mostrado por página"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Redirección principal por defecto"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"La redirección que será usada cuando ninguna aplicación sea especificada."
-
-#: core/app_settings.py:268
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "La clave debe tener 16, 24 o 32 bytes de longitud"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Sintaxis inválida"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
#, fuzzy
msgid "Invalid rounds number"
msgstr "Petición inválida"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Este campo es obligatorio"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Mostrar"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Idioma preferido"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Idioma preferido para mostrar las páginas"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Nombre de usuario"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Contraseña"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Contraseña anterior"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Nueva contraseña"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Confirmación"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "La contraseña no concuerda con la anterior"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Las contraseñas no coinciden"
-
-#: core/models.py:50
+#: core/models.py:52
#, fuzzy
msgid "password"
msgstr "Contraseña"
-
-#: core/models.py:52
+#: core/models.py:54
#, fuzzy
msgid "last login"
msgstr "Última entrada"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "No puede eliminar su propia cuenta"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Falló al actualizar la contraseña: módulo LDAP no instalado"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "cuenta"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Línea inválida"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "No puede importar una cuenta con un rol mayor que el suyo"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "El usuario normal '%s' debe tener una dirección de email válida"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr ""
"Los campos de nombre de usuario y de email no deben ser diferentes para '%s'"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "activado"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Marcar para activar esta extensión"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "añadido"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "modificado"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s por el usuario %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "eliminado"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Extensiones"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Elija las extensión(es) a usar"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Nombre"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Versión"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Descripción"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Guardar"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Información"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Información varia sobre Modoboa"
-
#: core/templates/core/information.html:5
#, fuzzy
msgid "An update is available!"
msgstr "No hay estadísticas disponibles"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
@@ -477,147 +342,105 @@ msgid ""
"\">here.\n"
" "
msgstr ""
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "está actualmente en uso."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Usuarios activos"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Nombre del grupo"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Última entrada"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Logs"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Anteriormente en Modoboa..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Fecha"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Nivel"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Mensaje"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Parámetros"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configurar Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Guardar"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Configuración de Modoboa"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Configuración"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Preferencias"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Adaptar Modoboa"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Perfil"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Actualizar su información personal"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Actualizar"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Salir"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Parámetros guardados"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Modificaciones aplicadas."
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Usuario '%s' ha entrado con éxito"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Su nombre de usuario y contraseña no concuerdan. Por favor, inténtelo de "
"nuevo."
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Usuario '%s' ha salido"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Perfil actualizado"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Preferencias guardadas"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Mensajes de test"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Enviar virus"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Enviar correo basura"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Mensaje enviado"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -649,2755 +472,182 @@ msgstr ""
"a \n"
" la lista "
"de correo .\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Consola de administración"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Consola web para administrar dominios, cuentas y alias"
-
-#: extensions/admin/__init__.py:57
-#, fuzzy
-msgid "Administration"
-msgstr "Administradores"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Dominios"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Identidades"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Siguiente"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Falló la importación de la cuenta (%s): el dominio no existe"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "El mailbox %s ya existe"
-
-#: extensions/admin/__init__.py:186
-#, fuzzy, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Falló la importación de la cuenta (%s): el dominio no existe"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-#, fuzzy
-msgid "domain alias"
-msgstr "Alias del dominio"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Mailboxes"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Manejar mailboxes en el sistema de fichero"
-
-#: extensions/admin/app_settings.py:19
-#, fuzzy
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr ""
-"Renombrar o eliminar mailboxes en el sistema de ficheros cuando sean "
-"renombrados o eliminados dentro de Modoboa"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Propietario de los mailboxes"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "Cuenta de UNIX que posee los mailboxes en el sistema de ficheros"
-
-#: extensions/admin/app_settings.py:33
-#, fuzzy
-msgid "Default domain quota"
-msgstr "Límites por defecto"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr ""
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Elminar cuentas automáticamente"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr "Cuando un mailbox es eliminado, también lo es su cuenta asociada."
-
-#: extensions/admin/app_settings.py:49
-#, fuzzy
-msgid "Automatic domain/mailbox creation"
-msgstr "Dominio creado"
-
-#: extensions/admin/app_settings.py:52
-msgid "Create a domain and a mailbox when an account is automatically created."
-msgstr ""
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr ""
-
-#: extensions/admin/lib.py:27
-#, fuzzy
-msgid "A mailbox is required"
-msgstr "Una cuota es obligatoria"
-
-#: extensions/admin/forms/account.py:23
-#, fuzzy
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr "El usuario normal '%s' debe tener una dirección de email válida"
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Rol"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Elija"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Qué nivel de permiso tendrá este usuario"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Introduzca la misma contraseña que arriba, para verificación."
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Activado"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Las contraseñas no concuerdan"
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "No puede deshabilitar su propia cuenta"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "Email"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Cuota"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr ""
-"Cuota en MB para este mailbox. Defina un valor por defecto o use el del "
-"dominio por defecto. Déjelo vacío para definir un valor ilimitado (no "
-"permitido para los administradores del dominio)"
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Alias"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr ""
-"Alias de este mailbox. Indique sólo una dirección por entrada, presione "
-"ENTER para añadir una nueva entrada. Use el carácter '*' para crear una "
-"dirección 'catchall' (recogerlos todos, ej. *@domain.tld)"
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "El dominio no existe"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Dominio(s)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Dominio(s) que el usuario administra"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Correo"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Permisos"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Cuenta actualizada"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Nueva cuenta"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Cuenta creada"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "Dirección de email"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr ""
-"La dirección de la lista de distribución. Use el carácter '*' para crear una "
-"dirección 'catchall' (recogerlos todos, ej. *@domain.tld)"
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Destinatarios"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr ""
-"Mailbox(es) a los que apuntará este alias. Indique únicamente una dirección "
-"por entrada, presione ENTER para añadir una nueva entrada."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "No tienes acceso a este dominio"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "mailbox inválido"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Destinatario local %s no encontrado"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "EL destinatario %s ya existe"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "No ha puesto destinatario"
-
-#: extensions/admin/forms/domain.py:24
-#, fuzzy
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr "Cuota por defecto en MB que se aplicará a los mailboxes"
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr ""
-"Alia(s) de este dominio. Indique únicamente un nombre por entrada, presione "
-"ENTER para añadir una nueva entrada."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, fuzzy, python-format
-msgid "A %s with this name already exists"
-msgstr "Ya existe un alias con este nombre"
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-#, fuzzy
-msgid "domain"
-msgstr "Dominios"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Crear un administrador del dominio"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Automáticamente crear una administrador para este dominio"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr ""
-"El nombre del administrador. No incluya el nombre del dominio aquí, será "
-"añadido automáticamente."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Crear alias"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Automáticamente crear alias estándar para este dominio"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Formato inválido"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "El usuario '%s' ya existe"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Dominio modificado"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Opciones"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Nuevo dominio"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Dominio creado"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Nombre del fichero"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Separador"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Destinatario(s)"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Indique uno o más destinatarios separados por una ','"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Mantener copias locales"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr "Reenvía mensajes y guarda copias en su mailbox local"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr ""
-"No puede definir un reenvío a un destino local. Por favor, pregunte a su "
-"administrador para crear un alias en su lugar."
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Seleccione un fichero"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Continúe en error."
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "No tratar objetos duplicados como error"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Contraseñas cifradas"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr ""
-"Marque esta opción si las contraseñas que contiene su fichero no están "
-"cifradas"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "dirección"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just "
-"enter an * character."
-msgstr ""
-"La dirección del alias (sin la parte del dominio). Para una dirección que lo "
-"recoja todo, ponga un asterisco (*)."
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "mailboxes"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "Los 'mailboxes' de este alias apuntan a"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Los alias de este alias apuntan a"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Marcar para activar este alias"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "Lista de distribución"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "reenvío"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Línea inválida: %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "El dominio '%s' no existe"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "nombre"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "Nombre del dominio"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Marcar para activar este dominio"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-#, fuzzy
-msgid "Domain"
-msgstr "Dominios"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr ""
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "Nombre del alias"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "objetivo"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "El dominio al que este alias apunta"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Dominio desconocido %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Dirección del mailbox (sin la parte @dominio.tld)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Fallo al recuperar la localización del mailbox (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "La cuota es mayor que el límite permitido para el dominio (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "Una cuota es obligatoria"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-#, fuzzy
-msgid "Domain is disabled"
-msgstr "Dominio eliminado"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "MB"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-#, fuzzy
-msgid "You can't create a new domain administrator"
-msgstr "Crear un administrador del dominio"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Estadísticas"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#, fuzzy
-msgid "Domains and identities"
-msgstr "Listar identidades"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-#, fuzzy
-msgid "Quantity"
-msgstr "Cuarentena"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Alias del dominio"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Tags"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Acciones"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-#, fuzzy
-msgid "disabled"
-msgstr "activado"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Administradores"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "No hay un dominio de administrador definido "
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Fecha de creación"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Última fecha de modificación"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Alias del mailbox"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Reenvía automáticamente los correos a otra dirección"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Nombre completo/Destinatario"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Ayuda"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Importando..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Elija un valor"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Usar el valor por defecto del dominio"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Dirección"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Valor"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Límite"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Uso (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Buscar"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "Activado"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "Activado"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-#, fuzzy
-msgid "List domains"
-msgstr "Editar el dominio"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Añadir dominio"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Importar"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Exportar"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Listar identidades"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Listar cuotas"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Añadir cuenta"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Añadir alias"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Añadir reenvío"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Añadir lista de distribución"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Ver las identidades del dominio"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "¿Eliminar %s?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Eliminar este permiso"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Ya existe un alias con este nombre"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Crear"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Nueva lista de distribución"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Lista de distribución creada"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Nuevo alias"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias creado"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Nuevo reenvío"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Reenvío creado"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Lista de distribución modificada"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Reenvío modificado"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Alias modificado"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "No puedo eliminar su propio dominio"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Dominio eliminado"
-msgstr[1] "Dominios eliminados"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Exportar identidades"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Exportar dominios"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Petición inválida"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Cuenta eliminada"
-msgstr[1] "Cuentas eliminadas"
-
-#: extensions/admin/views/import.py:36
-#, fuzzy, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-"Provea un fichero CSV dónde las líneas respetan uno de los siguientes "
-"formatos:⏎ ⏎ dominio; nombre; cuota; activado ⏎ "
-"aliasdeldominio; nombre; dominio objetivo; activado ⏎ "
-"ul>⏎ El primer elemento de cada línea es obligatorio y debe ser igual a "
-"uno de los valores anteriores.
⏎ Puede usar un carácter diferente como "
-"separador.
⏎\n"
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Importar dominios"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "El objeto ya existe: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d objetos importados con éxito"
-
-#: extensions/admin/views/import.py:149
-#, fuzzy
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; "
-"address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-"Importe un fichero CSV dónde las líneas respetan uno de los siguientes "
-"formatos:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; "
-"address[, domain, ...] ⏎\n"
-"alias; address; enabled; internal recipient ⏎\n"
-"forward; address; enabled; external recipient ⏎\n"
-"dlist; address; enabled; recipient; recipient; ... ⏎\n"
-" ⏎\n"
-"El primer elemento de cada línea es obligatorio y debe ser igual al de "
-"los valores previos.
\n"
-"\n"
-"Puede usar un carácter diferente como separador.
\n"
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Importar identidades"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Reenvío actualizado"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Panel de gestión sencilla para amavis"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Cuarentena"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Configuración de la cuarentena"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Tiempo máximo del mensaje"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr ""
-"Máxima edad (en días) de los mensajes de cuarentena antes de proceder a su "
-"eliminación"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Publicando mensajes"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Eliminar mensajes publicados"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr ""
-"Eliminar los mensajes marcados como publicados cuando se haga limpieza de la "
-"base de datos"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Modo de conexión con Amavis"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Modo usado para acceder al servidor PDP"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "Dirección del servidor PDP"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "Dirección del servidor de PDP (si está en modo inet)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "Puerto del servidor PDP"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "Puerto del servidor de PDP (si está en modo inet)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "socket del servidor PDP"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Dirección del socket del servidor de PDP (si están en modo unix)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Permitir publicación directa"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Permitir a los usuarios enviar directamente sus mensajes"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Activar modo de autoservicio"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Activar el modo 'auto-servicio'"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Notificaciones al remitente"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "La dirección de correo usada para enviar notificaciones"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:99
-#, fuzzy
-msgid "Default user"
-msgstr "Editor por defecto"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:107
-#, fuzzy
-msgid "Spamd address"
-msgstr "De la dirección"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:113
-#, fuzzy
-msgid "Spamd port"
-msgstr "Correo basura"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Número de emails mostrados por página"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Fijar el número máxima de mensajes mostrados en una página"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr ""
-
-#: extensions/amavis/forms.py:94
-#, fuzzy
-msgid "Domain's database"
-msgstr "Alias del dominio"
-
-#: extensions/amavis/forms.py:96
-#, fuzzy
-msgid "User's database"
-msgstr "Buscar base"
-
-#: extensions/amavis/general_callbacks.py:149
-#, fuzzy
-msgid "Pending requests"
-msgstr "Peticiones pendientes"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Filtro de contenido"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "La conexión con amavis falló: %s"
-
-#: extensions/amavis/lib.py:131
-#, fuzzy
-msgid "No recipient found"
-msgstr "No ha puesto destinatario"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Filtro de virus"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "sí"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "no"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "Por defecto"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Saltarse la comprobación de virus o no. Elija 'Por defecto' para usar la "
-"configuración global."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Filtro de spam"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Saltarse la comprobación de spam o no. Elija 'Por defecto' para usar la "
-"configuración global."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Filtro de expulsados"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Saltarse la comprobación de expulsados o no. Elija 'Por defecto' para usar "
-"la configuración global."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Marcador de spam"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global "
-"settings."
-msgstr ""
-"Modificar el asunto del spam usando el texto especificado. Elija 'por "
-"defecto' para usar la configuración global."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Vaciar cuarentena"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Mensaje eliminado"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d mensaje eliminado correctamente"
-msgstr[1] "%(count)d mensajes eliminados correctamente"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Petición enviada"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Mensaje publicado"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d petición enviada"
-msgstr[1] "%(count)d peticiones enviadas"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d mensaje publicado correctamente"
-msgstr[1] "%(count)d mensajes publicados correctamente"
-
-#: extensions/amavis/views.py:360
-#, fuzzy, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d mensaje publicado correctamente"
-msgstr[1] "%(count)d mensajes publicados correctamente"
-
-#: extensions/amavis/views.py:394
-#, fuzzy
-msgid "Select a database"
-msgstr "Seleccione un fichero"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr ""
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Pendiente de publicar las peticiones"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Umbrales"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "o más es spam"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "o más lanza un mensaje de spam"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "A"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "Desde"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Tema"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-#, fuzzy
-msgid "Released"
-msgstr "Publicar"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-#, fuzzy
-msgid "Marked as spam"
-msgstr "Marcar mensajes"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-#, fuzzy
-msgid "Marked as non-spam"
-msgstr "Marcar mensajes"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Mantenimiento de la cuarentena"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-#, fuzzy
-msgid "Select"
-msgstr "Seleccione un fichero"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Correo basura"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-#, fuzzy
-msgid "Bad Header"
-msgstr "Mala cabecera"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Mal MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-#, fuzzy
-msgid "Banned"
-msgstr "Filtro de expulsados"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Publicar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Eliminar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-#, fuzzy
-msgid "Mark as spam"
-msgstr "Marcar mensajes"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Todos los mensajes"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-#, fuzzy
-msgid "Clean only"
-msgstr "Filtro de expulsados"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-#, fuzzy
-msgid "Spam only"
-msgstr "Correo basura"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-#, fuzzy
-msgid "Virus only"
-msgstr "Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-#, fuzzy
-msgid "Bad Header only"
-msgstr "Mala cabecera"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-#, fuzzy
-msgid "Bad MIME only"
-msgstr "Mal MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-#, fuzzy
-msgid "Banned only"
-msgstr "Filtro de expulsados"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] ""
-"\n"
-"%(counter)s petición de publicación está pendiente de acción.\n"
-msgstr[1] ""
-"\n"
-"%(counter)s peticiones de publicación están pendiente de acción.\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Esquema:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "Desde:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "Para:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Fecha:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Asunto:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Actuar sobre este mensaje"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Por favor, visite %(listingurl)s para un listado completo."
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Anterior"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Ver todas las cabeceras"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr ""
-"Recursos por administrador para limitar el número de objetos que pueden crear"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Límites"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Límites por defecto"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Administradores del dominio"
-
-#: extensions/limits/app_settings.py:15
-msgid "Maximum number of allowed domain administrators for a new administrator"
-msgstr ""
-"Número máximo de dominios permitido de administradores para un nuevo "
-"administrador"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Número máximo de dominios permitidos para un nuevo administrador"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr ""
-"Número máximo permitido de alias de dominio para un nuevo administrador"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Número máximo de mailboxes permitidas para un nuevo administrador"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Número máxido de alias permitidos para un nuevo administrador"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Límite inválido"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Sus recursos no han sido inicializados aún"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "No está autorizado definir valores ilimitados"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Revendedor"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Recursos"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s: límete alcanzado"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "No hay suficientes recursos"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr ""
-"Número máximo de administradores de dominio que este usuario puede crear"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Número máxima de dominios que este usuario puede crear"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Número máximo de alias de dominio que este usuario puede crear"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Número máximo de mailboxes que este usuario puede crear"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr "Número máximo de alias a mailboxes que este usuario puede crear"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "no definido"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "ilimitado"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Uso de recursos"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Funcionalidad de autorespuesta (vacaciones) usando Postfix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Contestaciones automáticas"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Tiempo de caducidad de respuestas automáticas"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr "Tiempo en segundos entre dos autorespuestas para el mismo emisor"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-#, fuzzy
-msgid "Default subject"
-msgstr "Editor por defecto"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:30
-#, fuzzy
-msgid "Default content"
-msgstr "Editor por defecto"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:12
-#, fuzzy
-msgid "Activate your auto reply from this date"
-msgstr "Activar su autorespuesta hasta esta fecha"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Hasta"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Activar su autorespuesta hasta esta fecha"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Esta fecha ha pasado"
-
-#: extensions/postfix_autoreply/forms.py:77
-#, fuzzy
-msgid "Must be greater than start date"
-msgstr "es mayor que"
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Mensaje de autorespuesta"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr ""
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr ""
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "asunto"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "El asunto que aparecerán en los correos enviados"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "contenido"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "El contenido que aparecerá en los emails enviados"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Activar/desactivar su autorespuesta"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "El mensaje de autorespuesta se ha actualizado correctamente."
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr ""
-"Defina el mensaje que automáticamente se enviará cuando esté desconectado"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr ""
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-#, fuzzy
-msgid "Relay domains"
-msgstr "Nuevo dominio"
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr ""
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-#, fuzzy
-msgid "Path to the master.cf configuration file"
-msgstr "Ruta del fichero de log"
-
-#: extensions/postfix_relay_domains/forms.py:20
-#, fuzzy
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr ""
-"Alia(s) de este dominio. Indique únicamente un nombre por entrada, presione "
-"ENTER para añadir una nueva entrada."
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-#, fuzzy
-msgid "relay domain alias"
-msgstr "Alias del dominio"
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-#, fuzzy
-msgid "relay domain"
-msgstr "Nuevo dominio"
-
-#: extensions/postfix_relay_domains/forms.py:186
-#, fuzzy
-msgid "Relay domain modified"
-msgstr "Dominio modificado"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-#, fuzzy
-msgid "Add relay domain"
-msgstr "Añadir dominio"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-#, fuzzy
-msgid "Maximum number of relay domains this user can create"
-msgstr "Número máxima de dominios que este usuario puede crear"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-#, fuzzy
-msgid "Relay domain aliases"
-msgstr "Alias del dominio"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-#, fuzzy
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr "Número máximo de alias de dominio que este usuario puede crear"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients"
-"em> \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr ""
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-#, fuzzy
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr "Número máximo de dominios permitidos para un nuevo administrador"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-#, fuzzy
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr ""
-"Número máximo permitido de alias de dominio para un nuevo administrador"
-
-#: extensions/postfix_relay_domains/models.py:59
-#, fuzzy
-msgid "The service name"
-msgstr "Nombre del alias"
-
-#: extensions/postfix_relay_domains/models.py:80
-#, fuzzy
-msgid "target host"
-msgstr "objetivo"
-
-#: extensions/postfix_relay_domains/models.py:81
-#, fuzzy
-msgid "Remote destination of this domain"
-msgstr "Marcar para activar este dominio"
-
-#: extensions/postfix_relay_domains/models.py:89
-#, fuzzy
-msgid "verify recipients"
-msgstr "Destinatarios"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:103
-#, fuzzy
-msgid "Relay Domain"
-msgstr "Nuevo dominio"
-
-#: extensions/postfix_relay_domains/models.py:164
-#, fuzzy
-msgid "The relay domain this alias points to"
-msgstr "El dominio al que este alias apunta"
-
-#: extensions/postfix_relay_domains/models.py:195
-#, fuzzy, python-format
-msgid "Relay domain %s does not exist"
-msgstr "El dominio '%s' no existe"
-
-#: extensions/postfix_relay_domains/views.py:28
-#, fuzzy
-msgid "Relay domain created"
-msgstr "Dominio creado"
-
-#: extensions/postfix_relay_domains/views.py:33
-#, fuzzy
-msgid "New relay domain"
-msgstr "Nuevo dominio"
-
-#: extensions/postfix_relay_domains/views.py:61
-#, fuzzy
-msgid "Relay domain deleted"
-msgstr "Dominio eliminado"
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr ""
-
-#: extensions/radicale/__init__.py:34
-#, fuzzy
-msgid "Radicale management"
-msgstr "Mantenimiento de la cuarentena"
-
-#: extensions/radicale/__init__.py:38
-msgid "Management frontend for Radicale, a simple calendar and contact server."
-msgstr ""
-
-#: extensions/radicale/app_settings.py:11
-#, fuzzy
-msgid "Server settings"
-msgstr "Configuración por usuario"
-
-#: extensions/radicale/app_settings.py:15
-#, fuzzy
-msgid "Server URL"
-msgstr "Puerto del servidor"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr ""
-
-#: extensions/radicale/app_settings.py:24
-#, fuzzy
-msgid "Rights management"
-msgstr "Mantenimiento de la cuarentena"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:36
-#, fuzzy
-msgid "Allow calendars administration"
-msgstr "Administrador de dominio"
-
-#: extensions/radicale/app_settings.py:39
-#, fuzzy
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr ""
-"Número máximo de administradores de dominio que este usuario puede crear"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr ""
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr ""
-
-#: extensions/radicale/forms.py:134
-#, fuzzy, python-format
-msgid "Mailbox %s does not exist"
-msgstr "El dominio '%s' no existe"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr ""
-
-#: extensions/radicale/forms.py:162
-#, fuzzy
-msgid "New calendar"
-msgstr "Nuevo alias"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-#, fuzzy
-msgid "Calendar created"
-msgstr "Filtro creado"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-#, fuzzy
-msgid "Calendar updated"
-msgstr "Perfil actualizado"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr ""
-
-#: extensions/radicale/models.py:94
-#, fuzzy
-msgid "User"
-msgstr "Nombre de usuario"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr ""
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-#, fuzzy
-msgid "Calendar removed"
-msgstr "Filtro eliminado"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr ""
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr ""
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr ""
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-#, fuzzy
-msgid "Add calendar"
-msgstr "Añadir alias"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr ""
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Extensión para crear filtros en el servidor de forma sencilla"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "filtros Sieve"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Filtros de mensajes"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "Configuración de ManageSieve"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Dirección de su servidor MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "Puerto a la escucha de su servidor MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Conectar usando STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Usar la extensión STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Mecanismos de autenticación"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Mecanismo de autenticación preferido"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Modo editor"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Seleccione el modo en el que desea que el editor trabaje"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Marcar para activar este conjunto de filtros"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Todos los siguientes"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Cualquiera de los siguientes"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "contiene"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "no contiene"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "es"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "no es"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Remitente"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Destinatario"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Cc"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Tamaño"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "es mayor que"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "es menor que"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Mover el mensaje a"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Redirigir el mensaje a"
-
-#: extensions/sievefilters/forms.py:110
-#, fuzzy
-msgid "Wrong filter name"
-msgstr "Nombre del fichero"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr "La conexión al servidor MANAGESIEVE falló, verifique su configuración."
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "No hay suficiente espacio en el servidor"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Fallo en la recuperación de un conjunto de filtros"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Nuevo filtro"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filtro creado"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Editar filtro"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filtro modificado"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filtro eliminado"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "La eliminación del filtro falló"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Filtros guardados"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Conjunto de filtros creado"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Crear un nuevo conjunto de filtros"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Conjunto de filtros eliminado"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Conjunto de filtros activado"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Condiciones"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Activo"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "No hay un filtro definido aún"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Conjunto de filtros"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "activo"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr ""
-"No hay un conjunto de filtros definido aún. Debe crear uno para poder "
-"definir filtros."
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Nuevo conjunto de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Guardar conjunto de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Activar conjunto de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Eliminar conjunto de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Descargar"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Eliminar este filtro"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Subir este filtro"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Bajar este filtro"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Estadísticas gráficas del tráfico de emails usando RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Estadísticas gráficas"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Ruta del fichero de log"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Ruta al fichero de log usado para recolectar estadísticas"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Directorio para guardar los ficheros RRD"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Ruta al directorio dónde están almacenados los ficheros RRD"
-
-#: extensions/stats/graphics.py:98
-#, fuzzy
-msgid "Average traffic (msgs/min)"
-msgstr "Tamaño medio de tráfico normal"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "mensajes enviados"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "mensajes recibidos"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "mensajes rebotados"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "mensajes bloqueados"
-
-#: extensions/stats/graphics.py:112
-#, fuzzy
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Tamaño medio de tráfico normal"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "tamaño recibido"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "tamaño enviado"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Tráfico de correo"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "No hay estadísticas disponibles"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Día"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Semana"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Mes"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Año"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr ""
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Conjunto gráfico desconocido"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Período elegido erróneo"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Buscar un dominio"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Aplicar"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Correo web sencillo para IMAP"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Máximo tamaño de los adjuntos"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Tamaño máximo del adjunto en bytes (or KB, MB, GB si se especifica)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "Configuración de IMAP"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Dirección de su servidor IMAP"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Usar una conexión segura para acceder al servidor IMAP"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Puerto de su servidor IMAP"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "Configuración de SMTP"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Dirección de su servidor SMTP"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Modo de conexión seguro"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Nada"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Usar una conexión segura para acceder al servidor SMTP"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Puerto de su servidor SMTP"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Autenticación obligatoria"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "El servidor requiere autenticación"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Modo por defecto para mostrar un mensaje"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "Modo por defecto usado cuando se muestra un mensaje"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Activar el mostrar enlaces de HTML"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Activar/Desactivar el mostrar enlaces HTML"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Fija el número máximo de mensajes mostrados en una página"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Tasa de refresco"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Tasa de refresco automática de la carpeta (en segundos)"
-
-#: extensions/webmail/app_settings.py:103
-#, fuzzy
-msgid "Mailboxes container's width"
-msgstr "Propietario de los mailboxes"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Carpeta de basura"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Carpeta dónde van los mensajes eliminados"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Carpeta de enviados"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Carpeta dónde van las copias de los correos enviados"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Carpeta de borradores"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Carpeta dónde van los borradores"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Composición de mensajes"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Editor por defecto"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "Editor por defecto para usar cuando redacta un mensaje"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Texto de la firma"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Firma de correo definida por el usuario"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr ""
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Respuesta del servidor"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Acción desconocida"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "Cco"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Correo web"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d mensaje eliminado"
-msgstr[1] "%(count)d mensajes eliminados"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Mailbox vacío"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Mailbox creado."
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Crear un nuevo mailbox"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Editar el mailbox"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Mailbox actualizado"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Fallo al guardar el adjunto:"
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "EL adjunto es demasiado grande (límite: %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Adjuntos"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Consulta errónea"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Fallo al eliminar el adjunto:"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Adjunto desconocido"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "escribió:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Mensaje original"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Fallo al recuperar el delimitador jerárquico"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "Falló la conexión con el servidor IMAP: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Adjunto"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Subiendo..."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Mailbox padre"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Responder"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Responder a todos"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Opciones de pantalla"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Activar enlaces"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Desactivar enlaces"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Enviar"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-#, fuzzy
-msgid "Mark as read"
-msgstr "Marcar mensajes"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-#, fuzzy
-msgid "Mark as unread"
-msgstr "Como no leído"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Vaciar la carpeta"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Editar el mailbox seleccionado"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Eliminar el mailbox seleccionado"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Comprimir la carpeta"
-
-#: lib/dbutils.py:36
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Mensaje enviado"
+#: lib/db_utils.py:39
#, fuzzy, python-format
msgid "Connection to database %s not configured"
msgstr "La conexión con amavis falló: %s"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Permiso denegado: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Permiso denegado"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr ""
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Petición inválida"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Introduzca un nombre dominio válido"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Sí"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "No "
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Falló la actualización de la contraseña: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Usuario normal"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super administrador"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Administrador de dominio"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Lo siento"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "La página pedida no existe."
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Ocurrió un error interno."
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Buscar..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "De la dirección"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Tema"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Ambos"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Error:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Ayuda:"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Cerrar"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Anterior"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Siguiente"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Bienvenido a Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Recuerdame"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Entrar"
-
#, fuzzy
-#~ msgid "Server location"
-#~ msgstr "Puerto del servidor"
-
-#~ msgid "Filter"
-#~ msgstr "FIltro"
-
-#~ msgid "Check requests interval"
-#~ msgstr "Intervalo de las peticiones de chequeo"
-
-#~ msgid "pending requests"
-#~ msgstr "Peticiones pendientes"
-
-#~ msgid "Average normal traffic"
-#~ msgstr "Media de tráfico normal"
-
-#~ msgid "msgs/min"
-#~ msgstr "msjs/min"
-
-#~ msgid "Average bad traffic"
-#~ msgstr "Media de tráfico erróneo"
-
-#~ msgid "bytes/min"
-#~ msgstr "bytes/min"
-
-#~ msgid "Total"
-#~ msgstr "Total"
-
-#~ msgid "Predefined time ranges"
-#~ msgstr "Rangos de tiempo predefinidos"
-
-#~ msgid "Custom time range"
-#~ msgstr "Rango de tiempo definido"
-
-#~ msgid "Add Cc field"
-#~ msgstr "Añadir campo Cc"
-
-#~ msgid "Add Cci field"
-#~ msgstr "Añadir campo Cco"
-
-#~ msgid "%(counter)s file"
-#~ msgid_plural "%(counter)s files"
-#~ msgstr[0] "%(counter)s fichero"
-#~ msgstr[1] "%(counter)s ficheros"
-
-#~ msgid "Mailbox quota"
-#~ msgstr "Cuota del mailbox"
-
-#~ msgid "Close this message"
-#~ msgstr "Cerrar este mensaje"
-
-#~ msgid "New message"
-#~ msgstr "Nuevo mensaje"
-
-#~ msgid "Mark messages"
-#~ msgstr "Marcar mensajes"
-
-#~ msgid "As read"
-#~ msgstr "Como leído"
-
-#~ msgid "No entries to display"
-#~ msgstr "No hay entradas que mostrar"
-
-#~ msgid "activate"
-#~ msgstr "activo"
-
-#~ msgid "Powered by Modoboa"
-#~ msgstr "Tecnología Modoboa"
-
#, fuzzy
-#~ msgid "A domain %s already exists"
-#~ msgstr "El mailbox %s ya existe"
-
-#~ msgid "Directory to store PNG files"
-#~ msgstr "Directorio para guardar los ficheros PNG"
-
-#~ msgid "Path to directory where PNG files are stored"
-#~ msgstr "Ruta al directorio dónde están almacenados los ficheros PNG"
-
-#~ msgid "Failed to grant access (%s)"
-#~ msgstr "Fallo al dar acceso (%s)"
-
-#~ msgid "An alias with this name already exists"
-#~ msgstr "Ya existe un alias con este nombre"
-
-#~ msgid "A domain with this name already exists"
-#~ msgstr "Ya existe un dominio con este nombre"
-
-#~ msgid "%d pending requests"
-#~ msgstr "%d peticiones pendientes"
-
-#~ msgid "Content Class"
-#~ msgstr "Clase de contenido"
-
-#~ msgid "Nothing"
-#~ msgstr "Nada"
-
-#~ msgid "Bad request"
-#~ msgstr "Petición incorrecta"
-
-#~ msgid "Undefined action"
-#~ msgstr "Acción no definida"
-
-#~ msgid "User preferences"
-#~ msgstr "Preferencias del usuario"
-
-#~ msgid "You need a mailbox in order to define a forward"
-#~ msgstr "Necesita un mailbox para definir un reenvío"
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
diff --git a/modoboa/locale/es/LC_MESSAGES/djangojs.po b/modoboa/locale/es/LC_MESSAGES/djangojs.po
index f6140bebb..975e07ec2 100644
--- a/modoboa/locale/es/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/es/LC_MESSAGES/djangojs.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2013-06-03 16:32+0000\n"
"Last-Translator: Pedro Gracia \n"
"Language-Team: Spanish (http://www.transifex.com/projects/p/modoboa/language/"
@@ -19,196 +19,27 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "No eleminar el directorio del dominio"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Esta operación eliminará TODOS los datos asociados a este dominio."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr ""
-"Esta operación eliminará todos los datos asociados a este dominio, excepto "
-"las cuentas."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "No hay un administrador de dominio definido"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "No eliminar el directorio del mailbox"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "¿Publicar esta selección?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "¿Eliminar esta selección?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-#, fuzzy
-msgid "Mark this selection as spam?"
-msgstr "¿Publicar esta selección?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-#, fuzzy
-msgid "Mark this selection as non-spam?"
-msgstr "¿Publicar esta selección?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "¿Publicar este mensaje?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "¿Eliminar este mensaje?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Ver todas las cabeceras"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Esconder todas las cabeceras"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr ""
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr ""
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "¿Eliminar este filtro?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "¿Guardar cambios?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "¿Eliminar este conjunto de filtros?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "¿Activar este conjunto de filtros?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "activo"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Buscar un dominio"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr ""
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "¿Eliminar el mailbox seleccionado?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Mailbox eliminado"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Mensaje enviado"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "Moviendo %s mensaje"
-msgstr[1] "Moviendo %s mensajes"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Aviso"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Cancelar"
-
#: static/js/global.js:329
#, fuzzy
msgid "Internal error"
msgstr "Error interno"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr ""
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Buscar"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Buscar..."
-
-#~ msgid "%s file"
-#~ msgid_plural "%s files"
-#~ msgstr[0] "%s fichero"
-#~ msgstr[1] "%s ficheros"
-
-#~ msgid "Message deleted"
-#~ msgstr "Mensaje eliminado"
-
-#~ msgid "Delete this domain?"
-#~ msgstr "¿Eliminar este dominio?"
-
-#~ msgid "Delete this account?"
-#~ msgstr "¿Eliminar esta cuenta?"
-
-#~ msgid "Delete this list?"
-#~ msgstr "¿Eliminar esta lista?"
-
-#~ msgid "Delete this forward?"
-#~ msgstr "¿Eliminar este reenvío?"
-
-#~ msgid "Delete this alias?"
-#~ msgstr "¿Eliminar este alias?"
+#, fuzzy
+#, fuzzy
diff --git a/modoboa/locale/fr/LC_MESSAGES/django.po b/modoboa/locale/fr/LC_MESSAGES/django.po
index 2893564de..a204f0484 100644
--- a/modoboa/locale/fr/LC_MESSAGES/django.po
+++ b/modoboa/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: modoboa-1.1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2011-01-07 10:00+100\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: FR \n"
@@ -16,183 +16,135 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Général"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr "Nouvelle version de Modoboa disponible"
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Authentification"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Type d'authentification"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Locale"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Le backend utilisé pour l'authentification"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Méthode de chiffrement par défaut"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (faible)"
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (faible)"
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (faible)"
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (faible)"
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (faible)"
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr ""
"Méthode utilisée pour chiffrer les mots de passe des boites aux lettres"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr "Tours"
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
"Nombre de tours à utiliser (sha256crypt et sha512crypt uniquement). Doit "
"être compris entre 1000 et 999999999 inclue."
-
-#: core/app_settings.py:75
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Clé secrète"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Clé utilisée pour chiffrer/déchiffre les mots de passe"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Paramètres LDAP"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Adresse du serveur"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "L'adresse IP ou le nom DNS du serveur LDAP"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Port utilisé par le serveur"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Le port TCP utilisé par le serveur LDAP"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Utiliser une connexion sécurisée"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Utiliser une connextion SSL/TLS pour accéder au serveur LDAP"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Méthode d'authentification"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Recherche et connexion"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Connexion directe"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Choisir la méthode d'authentification à utiliser"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "ND de connexion"
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
msgstr ""
"Le nom distinctif à utiliser pour les connections au serveur LDAP. Laisser "
"vide pour une connexion anonyme"
-
-#: core/app_settings.py:127
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Mot de passe de connexion"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"Le mot de passe à utiliser pour les connections au serveur LDAP (avec 'ND de "
"connexion')"
-
-#: core/app_settings.py:139
+#: core/app_settings.py:134
msgid "Users search base"
msgstr "Base de recherche des utilisateurs"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr ""
"Le nom distinctif de la base de recherche utilisée pour rechercher les "
"utilisateurs"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtre de recherche"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
msgstr ""
"Un filtre de recherche optionel (ex. '(objectClass=person)'). Pour être "
"valide, il doit être entouré de parenthèses."
-
-#: core/app_settings.py:160
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Modèle de nom distinctif utilisateur"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
@@ -200,28 +152,22 @@ msgid ""
msgstr ""
"Le modèle utilisé pour construire le nom distinctif d'un utilisateur. Il "
"doit contenir un espace réservé (ex. %(user)s)"
-
-#: core/app_settings.py:171
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Attribut 'mot de passe'"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "L'attribut utilisé pour stocker les mots de passe"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Indiquer si le serveur LDAP est un Active Directory ou pas"
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Groupes administrateurs"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
@@ -229,241 +175,160 @@ msgstr ""
"Les membres de ces groupes LDAP (Posix) seront créés en tant "
"qu'administrateurs de domaine. Utiliser des caractères ';' pour séparer les "
"groupes."
-
-#: core/app_settings.py:195
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Base de recherche des groupes"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr ""
"Le nom distinctif de la base de recherche utilisée pour rechercher les "
"groupes"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Divers"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Intervalle de vérification des notifications"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Intervalle entre deux vérifications de notification"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Vérifier les nouvelles versions"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Vérifie automatiquement si une nouvelle version est disponible"
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Age maximal d'un enregistrement du journal"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "L'age maximal en jours d'un enregistrement du journal"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Eléments par page"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Nombre d'éléments affichés par page"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Redirection par défaut"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"La redirection appliquée par défaut quand aucune application n'est spécifiée"
-
-#: core/app_settings.py:268
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "La longueur d'une clé doit être de 16, 24 ou 32 octets"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Syntaxe invalide"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Nombre invalide de tours"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Ce champ est requis"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Afficher"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Langage préféré"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Langage préféré pour afficher les pages"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Nom d'utilisateur"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Mot de passe"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Ancien mot de passe"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Nouveau mot de passe"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Confirmation"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "L'ancien mot de passe est incorrect"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Les mots de passe diffèrent"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr "mot de passe"
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr "dernière connexion"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Vous ne pouvez pas supprimer votre propre compte"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr ""
"Echec de la mise à jour du mot de passe : le module LDAP n'est pas installé"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "compte"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Ligne invalide"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "Vous ne pouvez pas importer un compte avec un rôle supérieur au votre"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "L'utilisateur simple '%s' doit avoir une adresse email valide"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "Les champs username et email de '%s' ne doivent pas différer"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "Activé"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Cocher pour activer cette extension"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "ajouté"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "modifié"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s par l'utilisateur %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "Supprimé"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Extensions"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Choisir les extensions à utiliser"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Nom"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Version"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Description"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Enregistrer"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Information"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informations variées à propos de Modoboa"
-
#: core/templates/core/information.html:5
msgid "An update is available!"
msgstr "Une mise à jour est disponible!"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
@@ -478,147 +343,105 @@ msgstr ""
"liste des changements est disponible ici .\n"
" "
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "est actuellement utilisé."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Utilisateurs actifs"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Nom du groupe"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Dernière connexion"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Journaux"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Précédemment dans Modoboa..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Date"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Niveau"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Message"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Paramètres"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configurez Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Enregistrer"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Paramètres de Modoboa"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Configuration"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Préférences"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Personnalisez Modoboa"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Profil"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Mettez à jour vos informations personnelles"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Mettre à jour"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Déconnexion"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Paramètres enregistrés"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Modifications appliquées."
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Utiliseur '%s' connecté avec succès"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Votre nom d'utilisateur et mot de passe ne correspondent pas. Veuillez "
"réessayer."
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Utilisateur '%s' déconnecté"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profil mis à jour"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Préférences enregistrées"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Message de test"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Envoyer un virus"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Envoyer un spam"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Message envoyé"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -649,2597 +472,93 @@ msgstr ""
"Veuillez svp rapporter toute erreur sur \n"
" la liste "
"de diffusion .
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Console d'administration"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Console web pour gérer les domains, comptes et alias"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr "Administration"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Domaines"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Identités"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Transfert"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "L'import du compte a échoué (%s): le domaine n'existe pas"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "La boite %s existe déjà"
-
-#: extensions/admin/__init__.py:186
-#, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "L'import du compte a échoué (%s): mauvais quota"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr "alias de domaine"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Boites"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Gérer les boites sur le système de fichiers"
-
-#: extensions/admin/app_settings.py:19
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr ""
-"Renommer ou supprimer les boites sur le système de fichiers quand elles sont "
-"renommées ou supprimées dans Modoboa"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Propriétaire des boites"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "Le compte UNIX qui possède les boites sur le système de fichiers"
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr "Quota de domaine par défaut"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr ""
-"Quota par défaut (en Mo) appliqué aux domaines fraichement créés et ne "
-"spécifiant pas de valeur. 0 signifie qu'aucun quota ne sera appliqué."
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Suppression automatique de compte"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr ""
-"Lorsqu'une boite aux lettres est supprimée, supprimer le compte associé en "
-"même temps"
-
-#: extensions/admin/app_settings.py:49
-msgid "Automatic domain/mailbox creation"
-msgstr "Création automatique de domaine/boite aux lettres"
-
-#: extensions/admin/app_settings.py:52
-msgid "Create a domain and a mailbox when an account is automatically created."
-msgstr ""
-"Créer un domaine et une boite aux lettres quand un compte est créé "
-"automatiquement."
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr "Doit être un entier positif"
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr "Une boite aux lettres est requise"
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr ""
-"Le nom de l'utilisateur. Doit être une adresse e-mail valide pour les "
-"utilisateurs simples ou les administrateurs avec une boite aux lettres."
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Rôle"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Choisir"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Quel niveau de permission cet utilisateur aura"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Entrer le même mot de passe, pour vérification."
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Activé"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Les deux mots de passe ne correspondent pas."
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "Vous ne pouvez pas désactiver votre propre compte"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "E-mail"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Quota"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr ""
-"Quota en Mo pour cette boite. Définir une valeur spécifique ou utiliser la "
-"valeur par défaut du domaine. Laisser vide pour définir une valeur illimitée "
-"(interdit pour les admins. de domaine)."
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Alias"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr ""
-"Alias de cette boite. Indiquer seulement une adresse par champ, appuyer sur "
-"ENTREE pour ajouter un nouveau champ. Utiliser le caractère '*' pour créer "
-"une adresse 'attrape tout' (ex: *@domain.tld)."
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "Domaine inexistant"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Domaine(s)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Domaine(s) que cet utilisateur administre"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Courrier"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Permissions"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Compte mis à jour"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Nouveau compte"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Compte créé"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "Adresse email"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr ""
-"L'adresse de la liste de distribution. Utiliser le caractère '*' pour créer "
-"une adresse 'attrape tout' (ex: *@domain.tld)."
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Destinataires"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr ""
-"Destinataire(s) de cet alias. Indiquer seulement une adresse par champ, "
-"appuyer sur ENTREE pour ajouter un nouveau champ."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "Vous n'avez pas accès à ce domaine"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Boite aux lettres invalide"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Destinataire local %s introuvable"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "Destinataire %s déjà présent"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Aucune destinataire défini"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr ""
-"Quota par défaut en Mo appliqué aux boites aux lettres. Laisser vide pour "
-"utiliser la valeur par défaut."
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr ""
-"Alias de ce domaine. Indiquer seulement un nom par champ, appuyer sur ENTREE "
-"pour ajouter un nouveau champ."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr "Un %s de ce nom existe déjà"
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr "domaine"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Créer un administrateur de domaine"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Créer automatiquement un administrateur pour ce domaine"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr ""
-"Le nom de l'administrateur. Ne pas include un nom de domaine ici, il sera "
-"ajouté automatiquement."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Créer des alias"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Créer automatiquement des alias standard pour ce domaine"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Format invalide"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "L'utilisateur '%s' existe déjà"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Domaine modifié"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Options"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Nouveau domaine"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Domaine créé"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Nom du fichier"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Séparateur"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Destinataire(s)"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Indiquer un ou plusieurs destinataires séparés par une ','"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Conserver des copies locales"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr "Transférer les messages et conserver une copie dans votre boite locale"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr ""
-"Vous ne pouvez pas définir un transfert vers une destination locale. "
-"Veuillez plutôt demander à votre administrateur de créer un alias"
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Sélectionner un fichier"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Continuer en cas d'erreur"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Ne pas traiter les objets dupliqués comme des erreurs"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Chiffrer les mots de passe"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr ""
-"Cocher cette option si les mots de passe contenus dans votre fichier ne sont "
-"pas chiffrés"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "Adresse"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just "
-"enter an * character."
-msgstr ""
-"L'adresse de l'alias (sans la partie domaine). Pour une adresse 'attrape-"
-"tout', entrer juste un caractère *."
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "Boites aux lettres"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "Les boites aux lettres sur lesquelles pointe cet alias"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Les alias vers lesquels pointe cet alias"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Cocher pour activer cet alias"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "liste de distribution"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "transfert"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Ligne invalide : %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "Domaine '%s' inexistant"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "Nom"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "Le nom du domaine"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Cocher pour activer ce domaine"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr "Domaine"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr "Quota invalide pour le domaine '%s'"
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "Le nom de l'alias"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "cible"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "Le domaine vers lequel cet alias pointe"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Domaine %s inconnu"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Adresse de la boite aux lettres (sans la partie @domain.tld)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Impossible de récuperer l'emplacement de la boite (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "Le quota est supérieur à la limité autorisée pour le domaine (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "Un quota est requis"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-msgid "Domain is disabled"
-msgstr "Le domaine est désactivé"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "Mo"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr "Vous ne pouvez pas créer de nouvel administrateur de domaine"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Statistiques"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-msgid "Domains and identities"
-msgstr "Domaines et identités"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr "Compteurs globaux"
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr "Type"
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-msgid "Quantity"
-msgstr "Quantité"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Alias de domaine"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr "Compteurs par domaine"
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Tags"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Actions"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-msgid "disabled"
-msgstr "Desactivé"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Administrateurs"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "Aucun administrateur de domaine défini"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Date de création"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Date de dernière modification"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Alias de boite."
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Transférer automatiquement les messages vers une autre adresse"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Nom complet/Destinataire"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Aide"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Import en cours..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Choisir une valeur"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Utiliser la valeur par défaut du domaine"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Adresse"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Valeur"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Limite"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Utilisation (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Chercher"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "Activé"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "Activée"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-msgid "List domains"
-msgstr "Lister les domaines"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Ajouter un domaine"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Importer"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Exporter"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Lister les identités"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Lister les quotas"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Ajouter un compte"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Ajouter un alias"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Ajouter un transfert"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Ajouter une liste de distribution"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Voir les identités du domaine"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "Supprimer %s ?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Supprimer cette permission"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Un alias de ce nom existe déjà"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Créer"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Nouvelle liste de distribution"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Liste de distribution créée"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Nouvel alias"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias créé"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Nouveau transfert"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Transfert créé"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Liste de distribution modifiée"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Transfert modifié"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Alias modifié"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "Vous ne pouvez pas supprimer votre propre domaine"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Domaine supprimé"
-msgstr[1] "Domaines supprimés"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Export d'identités"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Export de domaines"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Requête invalide"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Compte supprimé"
-msgstr[1] "Comptes supprimés"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-"Fournir un fichier CSV ou chaque ligne respècte un des formats suivants :\n"
-"\n"
-" domain; nom; quota; activé \n"
-" domainalias; nom; domaine cible; activé \n"
-" %s\n"
-" \n"
-"Le premier élément de chaque ligne est obligatoire et doit être égal à "
-"l'une des valeurs précédentes.
\n"
-"Vous pouvez utiliser un caractère différent comme séparateur.
\n"
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Importer des domaines"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "L'objet existe déjà : %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d objets importés avec succès"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; "
-"address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-"Fournir un fichier CSV ou chaque ligne respècte un des formats suivants :\n"
-"\n"
-"account; identifiant; mot de passe; prénom; nom; activé, groupe; "
-"addresse; quota; [, domaine, ...] \n"
-"alias; addresse; activé; destinataire interne \n"
-"forward; addresse; activé; destinataire externe \n"
-"dlist; addresse; activée; destinataire; destinataire; ... \n"
-" \n"
-"Le premier élément de chaque ligne est obligatoire et doit être égal à "
-"l'une des valeurs précédentes.
\n"
-"\n"
-"Vous pouvez utiliser un caractère différent comme séparateur.
\n"
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Importer des identités"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Transfert mis à jour"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Interface simplifiée pour la gestion d'amavis"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Quarantaine"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Paramètres de quarantaine"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Age maximal des messages"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr "Age maximum (en jours) des messages en quarantaine avant suppression"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Libération des messages"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Supprimer les messages libérés"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr ""
-"Supprimer les messages marqués comme relâchés pendant le nettoyage de la "
-"base de données"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Mode de connexion à Amavis"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Mode utilisé pour accéder au serveur PDP"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "Adresse du serveur PDP"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "Adresse du serveur PDP (en mode inet)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "Port du serveur PDP"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "Port du serveur PDP (en mode inet)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "Socket du serveur PDP"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Emplacement de la socket du serveur PDP (en mode unix)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Autoriser la libération directe"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Autoriser les utilisateurs à relâcher directement leurs messages"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Activer le mode 'libre service'"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Activer le mode 'libre service'"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Emetteur des notifications"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "L'adresse e-mail utilisée pour envoyer les notifications"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr "Apprentissage manuel"
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr "Activer l'apprentissage manuel"
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr ""
-"Autorise les super administrateurs à entrainer manuellement Spamassassin"
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr "Spamassassin est il local?"
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr "Indique si Spamassassin tourne sur le même serveur que Modoboa"
-
-#: extensions/amavis/app_settings.py:99
-msgid "Default user"
-msgstr "Utilisateur par défaut"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr "Nom de l'utilisateur possédant la base bayesienne par défaut"
-
-#: extensions/amavis/app_settings.py:107
-msgid "Spamd address"
-msgstr "Adresse de spamd"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr "L'adresse IP à laquelle spamd peut etre joint"
-
-#: extensions/amavis/app_settings.py:113
-msgid "Spamd port"
-msgstr "Port de spamd"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr "Le port TCP sur lequel écoute spamd"
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr "Activer l'apprentissage manuel niveau domaine"
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr ""
-"Autorise les administrateurs de domaine à entrainer Spamassassin (au sein de "
-"bases dédiées par domaine)"
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr "Activer l'apprentissage manuel par utilisateur"
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr ""
-"Autorise les utilisateur à entrainer personnellement Spamassassin (au sein "
-"d'une base dédiée)"
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Nombre d'emails affichés par page"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Définir le nombre maximal de messages affichés dans une page"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr "Base globale"
-
-#: extensions/amavis/forms.py:94
-msgid "Domain's database"
-msgstr "Base du domaine"
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr "Base de l'utilisateur"
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr "Requêtes en attente"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Filtrage de contenu"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "La connexion avec amavis a échoué : %s"
-
-#: extensions/amavis/lib.py:131
-msgid "No recipient found"
-msgstr "Aucun destinataire trouvé"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Filtrage des virus"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "oui"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "non"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "défaut"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Désactiver le filtrage des virus ou non. Choisir 'défaut' pour utiliser les "
-"paramètres globaux."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Filtrage du spam"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Désactiver le filtrage du spam ou non. Choisir 'défaut' pour utiliser les "
-"paramètres globaux."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Filtrage des messages bannis"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Désactiver le filtrage des messages bannis ou non. Choisir 'défaut' pour "
-"utiliser les paramètres globaux."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Marquage du spam"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global "
-"settings."
-msgstr ""
-"Modifier le sujet du spam en utilisant le texte spécifié. Choisir 'défaut' "
-"pour utiliser les paramètres globaux."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Quarantaine vide"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Message supprimé"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d message supprimé correctement"
-msgstr[1] "%(count)d messages supprimés correctement"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Requête envoyée"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Message relâché"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d requête envoyée"
-msgstr[1] "%(count)d requêtes envoyées"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d message relâché correctement"
-msgstr[1] "%(count)d messages relâchés correctement"
-
-#: extensions/amavis/views.py:360
-#, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d message traité correctement"
-msgstr[1] "%(count)d messages traités correctement"
-
-#: extensions/amavis/views.py:394
-msgid "Select a database"
-msgstr "Sélectionner une base"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr "Valider"
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] requêtes de libération en attente"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Seuils"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "ou plus est du spam"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "ou plus rejete le message"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr "Score"
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "A"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "De"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Sujet"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-msgid "Released"
-msgstr "Débloqué"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-msgid "Marked as spam"
-msgstr "Marqué comme spam"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-msgid "Marked as non-spam"
-msgstr "Marqué comme non-spam"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Gestion de la quarantaine"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr "Sélectionner"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr "Propre"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr "Mauvais entête"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Mauvais type MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr "Banni"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Débloquer"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Supprimer"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-msgid "Mark as spam"
-msgstr "Marquer comme spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr "Marquer comme non-spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Tous les messages"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr "Tout"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr "Seulement les propres"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr "Seulement le spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr "Seulement les virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr "Seulement les mauvais entêtes"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr "Seulement les mauvais types MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr "Seulement les bannis"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] ""
-"\n"
-"%(counter)s requête de libération est en attente d'une action.\n"
-msgstr[1] ""
-"\n"
-"%(counter)s requêtes de libération sont en attente d'une action.\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Aperçu :"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "De :"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "A :"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Date :"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Sujet :"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Agir sur ce message :"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Veuillez visiter %(listingurl)s pour une liste complète."
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Retour"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Afficher tous les entêtes"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr ""
-"Ressources par administrateur pour limiter le nombre d'objets qu'ils peuvent "
-"créer"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Limites"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Limites par défaut"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Admins de domaine"
-
-#: extensions/limits/app_settings.py:15
-msgid "Maximum number of allowed domain administrators for a new administrator"
-msgstr "Nombre maximal d'admins de domaine pour un nouvel administrateur"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Nombre maximal de domaines pour un nouvel administrateur"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr "Nombre maximal d'alias de domaine pour un nouvel administrateur"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Nombre maximal de boites pour un nouvel administrateur"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Nombre maximal d'alias de boite pour un nouvel administrateur"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Limite invalide"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Vos ressources ne sont pas encore initialisées"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "Vous n'êtes pas autorisé à définir des valeurs illimitées"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Revendeur"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Ressources"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s : limite atteinte"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Pas assez de ressources"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr "Nombre maximal d'admins de domaine que cet utilisateur peut créer"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Nombre maximal de domaines que cet utilisateur peut créer"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Nombre maximal d'alias de domain que cet utilisateur peut créer"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Nombre maximal de boites que cet utilisateur peut créer"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr "Nombre maximal d'alias de boite que cet utilisateur peut créer"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "Indéfini"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "illimité"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Utilisation des ressources"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Fonction de réponse automatique (vacances) utilisant Postfix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Réponses automatiques"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Délai d'expiration d'une réponse automatique"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr ""
-"Timeout en secondes entre deux réponses automatiques pour le même "
-"destinataire"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr "Sujet par défaut"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr "Je suis absent"
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr ""
-"Sujet par défaut utilisé quand un message d'absence est créé automatiquement"
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr "Contenu par défaut"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr ""
-"Je suis actuellement absent. Je vous répondrai dès mon retour.\n"
-"\n"
-"Cordialement,\n"
-"%(name)s\n"
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr ""
-"Contenu par défaut utilisé quand un message d'absence est créé "
-"automatiquement.La macro '%(name)s' sera remplacée par le nom complet de "
-"l'utilisateur."
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr "Activer votre réponse automatique à partir de cette date"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Jusqu'à"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Activer votre réponse automatique jusqu'à cette date"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Cette date est dépassée"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr "Doit être supérieure à la date de démarrage"
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Message de réponse automatique"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr "Activer la réponse automatique"
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr "Activer ou désactiver la réponse automatique via Postfix"
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "sujet"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "Le sujet qui apparaitra dans les emails envoyés"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "contenu"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "Le contenu qui apparaitra dans les emails envoyés"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Activer/Désactiver votre réponse automatique"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Message de réponse auto. mis à jour."
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr "Définir un message à envoyer automatiquement quand vous êtes absent"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr "Support des domaines relais pour Postfix"
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr "Domaines relais"
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr "Chemin d'accès vers le fichier master.cf de Postfix"
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr "Chemin d'accès vers le fichier de configuration master.cf"
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr ""
-"Alias de ce domaine relais. Indiquer seulement un nom par champ, appuyer sur "
-"ENTREE pour ajouter un nouveau champ."
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr "Alias de domaine relais"
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr "domaine relais"
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr "Domaine relais modifié"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr "Ajouter un domaine relais"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr "Nombre maximal de domaines relais que cet utilisateur peut créer"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr "Alias de domaine relais"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr ""
-"Nombre maximal d'alias de domaine relais que cet utilisateur peut créer"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients"
-"em> \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr ""
-"\n"
-"relaydomain; nom; hôte cible; service; activé; vérification des "
-"destinataires \n"
-"relaydomainalias; nom; cible; activé \n"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr "Nombre maximal de domaines relais pour un nouvel administrateur"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr "Nombre maximal d'alias de domaine relais pour un nouvel administrateur"
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr "Le nom du service"
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr "hôte cible"
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr "Adresse de destination de ce domaine"
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr "Vérifier les destinataires"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr "Vérifie si les destinataires sont valides (existent)"
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr "Domaine relais"
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr "Le domaine relais vers lequel cet alias pointe"
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr "Domaine relais '%s' inexistant"
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr "Domaine relais créé"
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr "Nouveau domaine relais"
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr "Domaine relais supprimé"
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr "Scanner"
-
-#: extensions/radicale/__init__.py:34
-msgid "Radicale management"
-msgstr "Gestion de Radicale"
-
-#: extensions/radicale/__init__.py:38
-msgid "Management frontend for Radicale, a simple calendar and contact server."
-msgstr ""
-"Console de gestion pour Radicale, un serveur simple de calendrier et de "
-"contact."
-
-#: extensions/radicale/app_settings.py:11
-msgid "Server settings"
-msgstr "Paramètres serveur"
-
-#: extensions/radicale/app_settings.py:15
-msgid "Server URL"
-msgstr "URL du serveur"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr ""
-"L'URL de votre serveur Radicale. Elle sera utilisée pour construire l'URL "
-"des calendriers."
-
-#: extensions/radicale/app_settings.py:24
-msgid "Rights management"
-msgstr "Gestion des droits"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr "Chemin d'accès du fichier contenant les droits"
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr "Chemin d'accès du fichier contenant la définition des droits"
-
-#: extensions/radicale/app_settings.py:36
-msgid "Allow calendars administration"
-msgstr "Autoriser l'administration des calendriers"
-
-#: extensions/radicale/app_settings.py:39
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr ""
-"Autorise les administrateurs de domaine à gérer les calendriers des "
-"utilisateurs (lecture et écriture)"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr "Lecture"
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr "Ecriture"
-
-#: extensions/radicale/forms.py:134
-#, python-format
-msgid "Mailbox %s does not exist"
-msgstr "Boite '%s' inexistante"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr "Droits"
-
-#: extensions/radicale/forms.py:162
-msgid "New calendar"
-msgstr "Nouveau calendrier"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-msgid "Calendar created"
-msgstr "Calendrier créé"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-msgid "Calendar updated"
-msgstr "Calendrier mis à jour"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr "Calendriers"
-
-#: extensions/radicale/models.py:94
-msgid "User"
-msgstr "Utilisateur"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr "Partagé"
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-msgid "Calendar removed"
-msgstr "Calendrier supprimé"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr "Nouveau calendrier partagé"
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr "Soumettre"
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr "Pour accéder à ce calendrier, utilisez l'adresse suivante :"
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr "Propriétaire"
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-msgid "Add calendar"
-msgstr "Ajouter un calendrier"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr "Ajouter un calendar partagé"
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr "Voir le détail du calendrier"
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr "Editer %s"
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Extension pour créer simplement des filtres côté serveur"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "Filtres Sieve"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Filtres de messages"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "Paramètres ManageSieve"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Adresse de votre serveur ManageSieve"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "Port d'écoute de votre serveur ManageSieve"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Se connecter en utilisant STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Utiliser l'extension STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Méthode d'authentification"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Méthode d'authentification préférée"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Mode de l'editeur"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Sélectionner le mode de fonctionnement de l'éditeur"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Cocher pour activer ce jeu de filtres"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Toutes les conditions suivantes"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Au moins une des conditions suivantes"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "contient"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "ne contient pas"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "est"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "n'est pas"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Expéditeur"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Destinataire"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Cc"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Taille"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "est supérieure à"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "est inférieure à"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Déplacer le message vers"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Rediriger le message vers"
-
-#: extensions/sievefilters/forms.py:110
-msgid "Wrong filter name"
-msgstr "Nom de filtre invalide"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr ""
-"La connexion au serveur ManageSieve a échoué, vérifiez votre configuration"
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Pas assez d'espace sur le serveur"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Impossible de récuperer le jeu de filtres"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Nouveau filtre"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filtre créé"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Editer le filtre"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filtre modifié"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filtre supprimé"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Impossible de supprimer le filtre"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Jeu de filtres sauvegardé"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Jeu de filtres créé"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Créer un nouveau jeu de filtres"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Jeu de filtres supprimé"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Jeu de filtres activé"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Conditions"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Actif"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Aucun filtre défini."
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Jeux de filtres"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "actif"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr ""
-"Aucun jeu de filtres défini. Vous devez en créer un pour pouvoir définir des "
-"filtres."
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Nouveau jeu de filtres"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Sauvegarder le jeu de filtres"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Activer le jeu de filtres"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Supprimer le jeu de filtres"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Télécharger"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Supprimer ce filtre"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Déplacer ce filtre vers le haut"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Déplacer ce filtre vers le bas"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr ""
-"Statistiques graphiques concernant le trafic des messages utilisant RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Statistiques graphiques"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Chemin d'accès vers le journal"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Emplacement du log utilisé pour collecter les statistiques"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Répertoire où stocker les fichiers RRD"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Emplacement du répertoire de stockage des fichiers RRD"
-
-#: extensions/stats/graphics.py:98
-msgid "Average traffic (msgs/min)"
-msgstr "Trafic moyen (msgs/min)"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "messages envoyés"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "messages reçus"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "messages non remis"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "messages rejetés"
-
-#: extensions/stats/graphics.py:112
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Taille moyenne du trafic normal (octets/min)"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "taille reçue"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "taille envoyée"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Trafic messagerie"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Aucune statistique disponible"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Jour"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Semaine"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Mois"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Année"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr "Personnalisée"
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Jeu de graphiques inconnu"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Mauvaise période personnalisée"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Chercher un domaine"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Appliquer"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Webmail IMAP simple"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Taille maximale d'une pièce jointe"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Taille maximum d'une pièce jointe en octets (ou Ko, Mo, Go si précisé)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "Paramètres IMAP"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Adresse de votre serveur IMAP"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Utiliser une connexion sécurisée pour accéder au serveur IMAP"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Port d'écoute de votre serveur IMAP"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "Paramètres SMTP"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Adresse de votre serveur SMTP"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Mode de connexion sécurisé"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Aucun"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Utiliser une connexion sécurisée pour accéder au serveur SMTP"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Port d'écoute de votre serveur SMTP"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Authentification requise"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "Le serveur nécessite une authentification"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Mode d'affichage par défaut d'un message"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "Le mode utilisé par défaut pour afficher un message"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Activer l'affichage des liens HTML"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Activer/Désactiver l'affichage des liens HTML"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Définit le nombre maximal de messages affichés dans une page"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Taux de rafraichissement de la liste"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Taux de rafraichissement automatique du dossier (en secondes)"
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr "Largeur du conteneur de boites aux lettres"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr "La largeur du conteneur de boites aux lettres"
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Dossier 'poubelle'"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Dossier de destination des messages supprimés"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Dossier 'envoyé'"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Dossier de destination des copies de messages envoyés"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Dossier 'brouillons'"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Dossier de destination des brouillons"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Composer des messages"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Editeur par défaut"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "L'éditeur a utiliser par défaut pour écrire un message"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Texte de signature"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Signature personnalisée"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr "La valeur doit être un entier positif (> 0)"
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Réponse du serveur"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Action inconnue"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "Cci"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Webmail"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d message supprimé"
-msgstr[1] "%(count)d messages supprimés"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Boite aux lettre vide"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Boite aux lettres créée"
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Créer une nouvelle boite aux lettres"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Editer la boite aux lettres"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Boite aux lettres mise à jour"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Impossible d'enregistrer la pièce jointe : "
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "Pièce jointe trop grosse (limite : %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Pièces jointes"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Mauvaise requête"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Impossible de supprimer la pièce jointe :"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Pièce jointe inconnue"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "a écrit :"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Message original"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Impossible de récuperer le séparateur de hiérarchie"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "La connexion au serveur IMAP a échoué : %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Joindre"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Envoi..."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Boite aux lettres parente"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr "Ecrire"
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Répondre"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Répondre à tous"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Afficher les options"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Activer les liens"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Désactiver les liens"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Envoyer"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-msgid "Mark as read"
-msgstr "Marquer comme lu"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-msgid "Mark as unread"
-msgstr "Marquer comme non lu"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Vider ce dossier"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Editer la boite aux lettres sélectionnée"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Supprimer la boite aux lettres sélectionnée"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Compresser ce dossier"
-
-#: lib/dbutils.py:36
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Message envoyé"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Connexion à la base de données %s non configurée"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Permission refusée : %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Permission refusée"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr "Soumettre"
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Requête invalide"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Entrer un nom de domaine valide"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Oui"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "Non"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Echec de la mise à jour du mot de passe : %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Utilisateur simple"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super administrateur"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Administrateur de domaine"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Désolé"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "La page demandée n'existe pas."
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Une erreur interne est survenue"
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Chercher..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Emetteur"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Sujet"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Tous"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Erreur :"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Aide :"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Fermer"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Précédent"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Suivant"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Bienvenue dans Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Se souvenir de moi"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Se connecter"
diff --git a/modoboa/locale/fr/LC_MESSAGES/djangojs.po b/modoboa/locale/fr/LC_MESSAGES/djangojs.po
index f2d6beed2..e5e6bbbd3 100644
--- a/modoboa/locale/fr/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/fr/LC_MESSAGES/djangojs.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: modoboa-1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2011-01-07 10:00+0100\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: FR \n"
@@ -16,170 +16,24 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Plus d'entrée de journal à afficher"
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr "Plus de domaine à afficher"
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "Ne pas supprimer le répertoire du domaine"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Cette opération supprimera TOUTES les données associées à ce domaine."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr ""
-"Cette opération supprimera toutes les données associées à ce domaine à "
-"l'excéption des comptes."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Aucun administrateur de domaine défini"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr "Plus d'identité à afficher"
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Ne pas supprimer le répertoire de la boite aux lettres"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr "Plus de quota à afficher"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr "Plus de message à afficher"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Débloquer cette sélection?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Supprimer cette sélection?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-msgid "Mark this selection as spam?"
-msgstr "Marquer cette sélection comme étant du spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-msgid "Mark this selection as non-spam?"
-msgstr "Marquer cette sélection comme n'étant pas du spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Débloquer ce message?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Supprimer ce message?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr "Marquer comme spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr "Marquer comme non-spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Afficher tous les entêtes"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Cacher les entêtes complets"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr "Services mis à jour"
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr "Plus de calendrier à afficher"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Supprimer ce filtre?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Enregistrer les changements?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Supprimer ce jeu de filtres?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Activer ce jeu de filtres?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "actif"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Checher un domaine"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr "Plus aucun message dans cette boite aux lettres"
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Supprimer la boite sélectionnée?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Boite aux lettres supprimée"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Message envoyé"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "Déplacement de %s message"
-msgstr[1] "Déplacement de %s messages"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Avertissement"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Annuler"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr "Erreur interne"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Plus d'entrée à afficher"
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Chercher"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Chercher..."
diff --git a/modoboa/locale/it/LC_MESSAGES/django.po b/modoboa/locale/it/LC_MESSAGES/django.po
index 8175d4cfd..ee7218d0e 100644
--- a/modoboa/locale/it/LC_MESSAGES/django.po
+++ b/modoboa/locale/it/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2013-12-23 00:56+0100\n"
"Last-Translator: Alberto Berti \n"
"Language-Team: ITALIANO \n"
@@ -16,183 +16,135 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Generale"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr ""
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autenticazione"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Tipo di autenticazione"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Locale"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Il backend utilizzato per l'autenticazione"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Schema password predefinito"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (debole)"
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (debole)"
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (debole)"
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (debole)"
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (debole)"
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr ""
"Schema utilizzato per la criptazione delle password delle caselle di posta"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr "Cicli"
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
"Numero di cicli da utilizzare (valido per sha256crypt e sha512crypt). "
"Dev'essere tra 1000 e 999999999, inclusivo."
-
-#: core/app_settings.py:75
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Chiave segreta"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Chiave utilizzata per criptare/decriptare le password"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Impostazioni LDAP"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Indirizzo del server"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "L'indirizzo IP associato al DNS name del server LDAP"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Porta del server"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Il numero della porta TCP utilizzata dal server LDAP"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Usa una connessione sicura"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Utilizza una connessione SSL/TLS per accedere al server LDAP"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Metodo di autenticazione"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Cerca e collega"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Collegamento diretto"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Scegli il metodo di autenticazione da usare"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "collega DN"
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
msgstr ""
"Nome particolare da usare quando ci si collega al server LDAP. Lasciare "
"vuoto per un collegamento anonimo"
-
-#: core/app_settings.py:127
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Password del collegamento"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"La password da utilizzare quando ci si collega al server LDAP (con 'Collega "
"DN')"
-
-#: core/app_settings.py:139
+#: core/app_settings.py:134
msgid "Users search base"
msgstr "Base ricerca per gli utenti"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr ""
"L'identificativo (dn:) della base di ricerca utilizzata per cercare gli "
"utenti"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtro ricerca"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
msgstr ""
"Stringa di filtraggio opzionale (p.es '(objectClass=person)'). Per essere "
"valida deve essere racchiusa tra parentesi."
-
-#: core/app_settings.py:160
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Modello DN dell'utente"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
@@ -200,28 +152,22 @@ msgid ""
msgstr ""
"Il modello utilizzato per comporre un DN dell'utente. Deve contenere un "
"segnaposto (p.es. %(user)s)"
-
-#: core/app_settings.py:171
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Attributo della password"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "L'attributo utilizzato per memorizzare le password dell'utente"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Segnala se il server LDAP è una Active Directory"
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Gruppi degli amministratori"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
@@ -229,244 +175,163 @@ msgstr ""
"Gli appartenenti a questi gruppi LDAP Posix avranno i privilegi di "
"amministratori di dominio. Utilizza il carattere ';' per separare valori "
"multipli."
-
-#: core/app_settings.py:195
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Base ricerca per i gruppi"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr ""
"L'identificatore (dn:) della base di ricerca utilizzato per trovare i gruppi"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Miscellanea"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
#, fuzzy
msgid "Top notifications check interval"
msgstr "Spedizione notifiche"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
#, fuzzy
msgid "Interval between two top notification checks"
msgstr "Intervallo tra due controlli delle request di rilascio "
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
#, fuzzy
msgid "Check new versions"
msgstr "Verifica validità destinatari"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr ""
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Età massima dei log"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "La persistenza massima in giorni dei log"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Elementi per pagina"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Numero degli elementi visualizzati in ciascuna pagina"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Reindirizzamento principale predefinito"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"Redirezione predefinita utilizzata quando non è specificata alcuna "
"applicazione"
-
-#: core/app_settings.py:268
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "La chiave può essere lunga solo 16, 24 o 32 bytes"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Sintassi errata"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Numero di cicli non valido"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Questo campo è obbligatorio"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Mostra"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Lingua preferita"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Lingua preferita per mostrare le pagine"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Nome utente"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Password"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Vecchia password"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Nuova password"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Conferma"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "La vecchia password non corrisponde"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "La password non corrisponde"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr "password"
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr "ultimo login"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Non puoi cancellare il tuo account"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Aggiornamento della password fallito: il modulo LDAP non è installato"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "account"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Riga non valida"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "Non puoi importare un account con un ruolo superiore al tuo"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "L'utente '%s' deve avere un indirizzo email valido"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "I campi nome utente e email di '%s' devono avere lo stesso valore"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "Attivato"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Seleziona per abilitare questa estensione"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "aggiunto"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "modificato"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s dell'utente %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "cancellato"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Estensioni"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Scegli l'estensione(i) da utilizzare"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Nome"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Versione"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Descrizione"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Salva"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Informazioni"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informazioni varie su Modoboa"
-
#: core/templates/core/information.html:5
#, fuzzy
msgid "An update is available!"
msgstr "Non sono disponibili statistiche"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
@@ -476,145 +341,103 @@ msgid ""
"\">here.\n"
" "
msgstr ""
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "è attualmente in uso."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Utenti attivi"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Nome gruppo"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Ultimo login"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Log"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Precedentemente su Modoboa ..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Data"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Livello"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Messaggio"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Parametri"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configura Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Salva"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Impostazioni Modoboa"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Impostazioni"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Preferenze"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Personalizza Modoboa"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Profilo"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Aggiorna le informazioni personali"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Aggiorna"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Esci"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Parametri salvati"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Modifiche applicate"
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "L'utente '%s? è correttamente registrato"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "Il tuo username e/o la tua password non corrispondono. Riprova."
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "L'utente '%s' è scollegato"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profilo aggiornato"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Preferenze salvate"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Messaggi di test"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Invia virus"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Invia spam"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Messaggio inviato"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -646,2708 +469,133 @@ msgstr ""
"Prego segnalare qualsiasi errore o inviare suggerimenti \n"
" alla \n"
"mailing list .
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Interfaccia amministrativa"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Interfaccia web per l'amministrazione di domini, account e alias"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr "Amministrazione"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Domini"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Identità"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Inoltra"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Importazione dell'account fallito (%s): il dominio non esiste"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "La casella di posta %s esiste già"
-
-#: extensions/admin/__init__.py:186
-#, fuzzy, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Importazione dell'account fallito (%s): il dominio non esiste"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr "alias del dominio"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Caselle di posta"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Gestione delle caselle di posta nel filsystem"
-
-#: extensions/admin/app_settings.py:19
-#, fuzzy
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr ""
-"Rinomina o rimuovi le caselle di posta nel filsystem quando sono rinominate "
-"o rimosse in Modoboa"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Proprietario delle caselle postali"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "L'account UNIX a cui appartengono le caselle postali nel filsystem"
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr "Quota predefinita per il domini"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr ""
-"Quota predefinita (in MB) applicata ai nuovi domini che non la specificano. "
-"Un valore 0 implica nessuna quota."
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Rimozione automatica dell'account"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr ""
-"Quando una casella postale viene rimossa rimuovi anche l'account associato"
-
-#: extensions/admin/app_settings.py:49
-#, fuzzy
-msgid "Automatic domain/mailbox creation"
-msgstr "Dominio creato"
-
-#: extensions/admin/app_settings.py:52
-msgid "Create a domain and a mailbox when an account is automatically created."
-msgstr ""
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr "Dev'essere un intero positivo"
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr "É necessaria una casella"
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr ""
-"Il nome dell'utente. Dev'essere un indirizzo e-mail per gli utenti semplici "
-"o gli amministratori che posseggono una casella"
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Ruolo"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Scegli"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Il livello di permessi che avrà questo utente"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr ""
-"Inserisci la medesima password che hai inserito sopra, per la verifica."
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Abilitato"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Le password nei due campi non corrispondono"
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "Tu non puoi disabilitare il tuo account"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "E-mail"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Quota"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr ""
-"Quota in MB per questo account. Stabilire un valore personalizzato o usare "
-"quello predefinito. Lasciare vuoto per non impostare limiti (non consentito "
-"per gli amministratori di dominio)."
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Alias"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr ""
-"Alias per questa casella di posta. Inserire un solo indirizzo alla volta, "
-"premere INVIO per aggiungere un nuovo elemento. Utilizzare il carattere '*' "
-"per creare un alias 'prenditutto' (p.es.: *@dominio.org)."
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "Il dominio non esiste"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Dominio(i)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Dominio(i) amministrato(i) dall'utente"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Posta"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Permessi"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Account aggiornato"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Nuovo account"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Account creato"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "Indirizzo email"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr "Elenco degli indirizzi di smistamento"
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Destinatari"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr ""
-"Casella(e) di posta a cui l'alias punterà. Inserire un solo indirizzo alla "
-"volta, premere INVIO per aggiungere un nuovo elemento."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "Non hai accesso a questo dominio"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Casella di posta non valida"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Il destinatario locale %s non è stato trovato"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "Il destinatario %s è già esistente"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Non è stato definito un destinatario"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr ""
-"Quota in MB predefinita applicata alle caselle di posta. Lascialo vuoto se "
-"vuoi applicare il valore predefinito."
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr ""
-"Alias per questo dominio. Inserire un solo nome alla volta, premere INVIO "
-"per aggiungere un nuovo elemento"
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr "Un %s con questo nome esiste già"
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr "dominio"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Crea un amministratore di dominio"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Crea automaticamente un amministratore per questo dominio"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr ""
-"Il nome dell'amministratore. Non includere il nome del dominio, verrà "
-"aggiunto automaticamente."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Crea alias"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Crea automaticamente gli alias standard per questo dominio"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Formato non valido"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "L'utente '%s' esiste già"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Dominio modificato"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Opzioni"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Nuovo dominio"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Dominio creato"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Nome del file"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Separatore"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Destinatario(i)"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Indicare uno o più destinatari separati da ','"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Mantieni copie locali"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr ""
-"Inoltra i messaggi e memorizza le copie nella tua casella di posta locale"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr ""
-"Non puoi definire l'inoltro con destinazione una cartella locale. Chiedi "
-"piuttosto all'amministratore di creare un alias."
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Seleziona un file"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Continuare in caso di errore"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Non considerare errore gli oggetti duplicati"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Cripta le password"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr ""
-"Seleziona questa opzione se le password contenute nel file non sono criptate"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "indirizzo"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just "
-"enter an * character."
-msgstr ""
-"L'indirizzo alternativo (senza la parte del dominio). Per un indirizzo "
-"'prenditutto' inserisci un carattere '*'."
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "caselle di posta"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "Le caselle di posta a cui punta questo alias"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Gli alias a cui questo alias puntano"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Seleziona per attivare questo alias"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "elenco di smistamento"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "inoltra"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Riga non valida: %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "Il dominio '%s' non esiste"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "nome"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "Il nome del dominio"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Seleziona per attivare questo dominio"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr "Dominio"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr "Valore della quota non valido per il dominio '%s'"
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "Il nome dell'alias"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "destinazione"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "Il dominio a cui punta questo alias"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Dominio sconosciuto %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Indirizzo della casella di posta (senza la parte @dominio.org)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Impossibile recuperare la posizione della casella di posta (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "La quota è maggiore del limite stabilito per il dominio (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "È richiesta una quota"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-#, fuzzy
-msgid "Domain is disabled"
-msgstr "Dominio cancellato"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "MB"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr "Non ti è possibile creare un amministratore di dominio"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Statistiche"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#, fuzzy
-msgid "Domains and identities"
-msgstr "Elenco identità"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-#, fuzzy
-msgid "Quantity"
-msgstr "Quarantena"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Alias del dominio"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Tag"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Azioni"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-#, fuzzy
-msgid "disabled"
-msgstr "Attivato"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Amministratori"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "Non è stato definito alcun amministratore di dominio"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Data di creazione"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Data dell'ultima modifica"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Alias delle caselle di posta"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Inoltra automaticamente le e-mail ad un altro indirizzo"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Nome completo/Destinatario"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Aiuto"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Importazione..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Scegli un valore"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Usa il valore predefinito"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Indirizzo"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Valore"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Limite"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Utilizzo (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Ricerca"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "Abilitato"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "Abilitata"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-#, fuzzy
-msgid "List domains"
-msgstr "Elenco quote"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Aggiungi dominio"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Importa"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Esporta"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Elenco identità"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Elenco quote"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Aggiungi account"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Aggiungi alias"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Aggiungi inoltro"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Aggiungi elenco di smistamento"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Visualizza le identita del dominio"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "Eliminare %s?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Rimuovi questo permesso"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Un alias con questo nome esiste già"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Crea"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Nuovo elenco di smistamento"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Elenco di smistamento creato"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Nuovo alias"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias creato"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Nuovo inoltro"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Inoltro creato"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Elenco di smistamento modificato"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Inoltro modificato"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Alias modificato"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "Non puoi cancellare il tuo dominio"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Dominio cancellato"
-msgstr[1] "Domini cancellati"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Identità di esportazione"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Esporta domini"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Richiesta non valida"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Account cancellato"
-msgstr[1] "Account cancellati"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-"Fornire un file CSV le cui righe rispettino uno dei seguenti formati:\n"
-"\n"
-" dominio; nome; quota; abilitato \n"
-" aliasdominio; nome; dominio di destinazione; abilitato \n"
-" %s\n"
-" \n"
-"Il primo elemento di ogni riga è obbligatorio e deve essere uguale a "
-"quello dei valori precedenti.
\n"
-"\n"
-"Come separatore puoi utilizzare un carattere diverso.
\n"
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Importa domini"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "L'oggetto esiste già: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d oggetti importati correttamente"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; "
-"address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-"Fornire un file CSV le cui righe rispettino uno dei seguenti formati:\n"
-"\n"
-"account; id utente; password; nome; cognome; abilitato; gruppo; "
-"indirizzo; quota; [, dominio, ...] \n"
-"alias; indirizzo; abilitato; destinatario interno \n"
-"forward; indirizzo; abilitato; destinatario esterno \n"
-"dlist; indirizzo; abilitato; destinatario; destinatario; ... "
-"li>\n"
-" \n"
-"Il primo elemento di ogni riga è obbligatorio e deve essere uguale a "
-"quello dei valori precedenti.
\n"
-"\n"
-"Come separatore puoi utilizzare un carattere diverso.
\n"
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Identità di importazione"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Inoltro aggiornato"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Interfaccia di gestione amavis semplice"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Quarantena"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Impostazioni quarantena"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Età massima dei messaggi"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr "Età massima dei messaggi in quarantena"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Rilascio messaggi"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Rimozione dei messaggi rilasciati"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr ""
-"Rimuovi i messaggi marcati come rilasciati durante la pulizia del database"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Modalità di connessione Amavis"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Modalità utilizzata per accedere al server PDP"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "Indirizzo del server PDP"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "Indirizzo del server PDP (se in modalità inet)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "Porta del server PDP"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "Porta del server PDP (se in modalità inet)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "Socket del server PDP"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Percorso al socket del server PDP (se in modalità UNIX)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Consenti il rilascio diretto"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Consenti agli utenti di rilasciare direttamente i loro messaggi"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Attiva la modalità self-service"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Attivazione della modalità 'self-service'"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Spedizione notifiche"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "L'indirizzo e-mail utilizzato per l'invio di notifiche"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:99
-#, fuzzy
-msgid "Default user"
-msgstr "Editor predefinito"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:107
-#, fuzzy
-msgid "Spamd address"
-msgstr "Mittente"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:113
-#, fuzzy
-msgid "Spamd port"
-msgstr "Solo messaggi di spam"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Numero di e-mail mostrate in ogni pagina"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Imposta il numero massimo di messaggi mostrati in una pagina"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr ""
-
-#: extensions/amavis/forms.py:94
-#, fuzzy
-msgid "Domain's database"
-msgstr "Alias del dominio"
-
-#: extensions/amavis/forms.py:96
-#, fuzzy
-msgid "User's database"
-msgstr "Base ricerca per gli utenti"
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr "Richieste in sospeso"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Filtro sui contenuti"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "Connessione ad amavis fallita: %s"
-
-#: extensions/amavis/lib.py:131
-#, fuzzy
-msgid "No recipient found"
-msgstr "Non è stato definito un destinatario"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Filtro virus"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "si"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "no"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "predefinito"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Aggirare il controllo virus o no. Scegliere 'predefinito' per utilizzare le "
-"impostazioni globali."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Filtro spam"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Aggirare il controllo spam o no. Scegliere 'predefinito' per utilizzare le "
-"impostazioni globali."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Filtro banned"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Aggirare il controllo banned o no. Scegliere 'predefinito' per utilizzare le "
-"impostazioni globali."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Contrassegno spam"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global "
-"settings."
-msgstr ""
-"Modifica dell'oggetto spam utilizzando un testo specifico. Scegliere "
-"'predefinito' per utilizzare le impostazioni globali."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Svuota quarantena"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Messaggio eliminato"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d messaggio eliminato con successo"
-msgstr[1] "%(count)d messaggi eliminati con successo"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Request inviata"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Messaggio rilasciato"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d request inviata"
-msgstr[1] "%(count)d request inviate"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d messaggio rilasciato con successo"
-msgstr[1] "%(count)d messaggi rilasciati con successo "
-
-#: extensions/amavis/views.py:360
-#, fuzzy, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d messaggio rilasciato con successo"
-msgstr[1] "%(count)d messaggi rilasciati con successo "
-
-#: extensions/amavis/views.py:394
-#, fuzzy
-msgid "Select a database"
-msgstr "Seleziona un file"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr ""
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Richieste di rilascio in sospeso"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Soglie"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "o più sono spam"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "o ulteriormente buttar via il messaggio spam"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr "Punteggio"
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "A"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "Da"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Oggetto"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-#, fuzzy
-msgid "Released"
-msgstr "Rilascia"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-#, fuzzy
-msgid "Marked as spam"
-msgstr "Contrassegna i messaggi"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-#, fuzzy
-msgid "Marked as non-spam"
-msgstr "Contrassegna i messaggi"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Gestione quarantena"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr "Seleziona"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr "Intestazione errata"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "MIME errato"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr "Banditi"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Rilascia"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Elimina"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-#, fuzzy
-msgid "Mark as spam"
-msgstr "Contrassegna i messaggi"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Tutti i messaggi"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr "Tutti"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-#, fuzzy
-msgid "Clean only"
-msgstr "Solo messaggi banditi"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr "Solo messaggi di spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr "Solo messaggi con virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr "Solo messaggi con intestazione errata"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr "Solo messaggi con struttura MIME errata"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr "Solo messaggi banditi"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] ""
-"\n"
-"%(counter)s richiesta di rilascio è in attesa di azioni\n"
-msgstr[1] ""
-"\n"
-"%(counter)s richieste di rilascio sono in attesa di azioni\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Sketch:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "Da:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "A:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Data:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Oggetto:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Agisci su questo messaggio:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Per un elenco completo prova a visitare %(listingurl)s"
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Indietro"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Visualizza tutte le intestazioni"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr ""
-"Risorse per amministratore. Limitazione del numero di oggetti che possono "
-"creare "
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Limiti"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Limiti predefiniti"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Amministratori di domini"
-
-#: extensions/limits/app_settings.py:15
-msgid "Maximum number of allowed domain administrators for a new administrator"
-msgstr ""
-"Numero massimo di amministratori di domini consentiti per un nuovo "
-"amministratore"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Numero massimo di domini consentiti per un nuovo amministratore"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr ""
-"Numero massimo di alias di dominio consentiti per un nuovo amministratore"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr ""
-"Numero massimo di caselle di posta consentite per un nuovo amministratore"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Numero massimo di alias consentiti per un nuovo amministratore"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Limite non valido"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Le tue risorse non sono ancora inizializzate"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "Non ti è consentito definire valori non limitati"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Rivenditore"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Risorse"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s: raggiunto il limite"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Risorse insufficienti"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr ""
-"Numero massimo di amministratori di dominio che questo utente può creare"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Numero massimo di domini che questo utente può creare"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Numero massimo di alias di dominio che questo utente può creare"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Numero massimo di caselle di posta che questo utente può creare"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr ""
-"Numero massimo di alias di caselle di posta che questo utente può creare"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "indefinito"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "senza limiti"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Utilizzo risorse"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Funzionalità di auto-risposta (per assenza) usando Postfix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Risposte automatiche"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Tempo massimo della risposta automatica"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr ""
-"Tempo massimo in secondi tra due risposte automatiche al medesimo "
-"destinatario"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr "Oggetto predefinito"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr "Sono via"
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr "Oggetto predefinito utilizzato nei messaggi di risposta automatica"
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr "Corpo del messaggio predefinito"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr ""
-"Al momento non posso rispondere. Risponderò al mio ritorno.\n"
-"\n"
-"Distinti saluti,\n"
-"%(name)s\n"
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr ""
-"Corpo del messaggio predefinito per i messaggi di risposta automatica. La "
-"macro '%(name)s' verrà sostituita con il nome dell'utente. "
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr "Attiva la risposta automatica da questa data"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Fino al"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Attiva la tua risposta automatica fino a questa data"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Questa data è passata"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr "Dev'essere successiva alla data di inizio"
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Messaggio di risposta automatica"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr "Abilita la risposta automatica"
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr "Abilita o disabilita la risposta automatica di Postfix"
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "oggetto"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "L'oggetto che apparirà nelle mail inviate"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "contenuto"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "Il contenuto che apparirà nelle mail inviate"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Attiva/disattiva la tua risposta automatica"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Messaggio di risposta automatica aggiornato con successo."
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr "Definisci un messaggio da inviare automaticamente quando sei via"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr "Supporto ai \"domini relè\" per Postfix"
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr "Domini relè"
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr "Percorso del file master.cf di Postfix"
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr "Percorso del file di configurazione master.cf"
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr ""
-"Alias per questo dominio relè. Inserisci un solo nome per casella, premi "
-"INVIO per aggiungere un nuovo elemento."
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr "Alias del dominio relè"
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr "Dominio relè"
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr "Dominio relè modificato"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr "Aggiungi dominio relè"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr "Numero massimo di domini relè che questo utente può creare"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr "Alias del dominio relè"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr ""
-"Numero massimo di alias di un dominio relè che questo utente può creare"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients"
-"em> \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr ""
-"\n"
-"dominio relè; nome; host di destinazione; servizio; abilitato; "
-"verifica caselle \n"
-" alias dominio relè; nome; destinazione; abilitato \n"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr "Numero massimo di domini relè consentiti per un nuovo amministratore"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr ""
-"Numero massimo di alias di dominio relè consentiti per un nuovo "
-"amministratore"
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr "Il nome del servizio"
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr "destinazione"
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr "Destinazione remota per questo dominio"
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr "Verifica destinatari"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr "Verifica validità destinatari"
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr "Dominio relè"
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr "Il dominio relè a cui punta questo alias"
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr "Il dominio relè '%s' non esiste"
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr "Dominio relè creato"
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr "Nuovo dominio relè"
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr "Dominio relè cancellato"
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr "Cerca"
-
-#: extensions/radicale/__init__.py:34
-#, fuzzy
-msgid "Radicale management"
-msgstr "Gestione quarantena"
-
-#: extensions/radicale/__init__.py:38
-msgid "Management frontend for Radicale, a simple calendar and contact server."
-msgstr ""
-
-#: extensions/radicale/app_settings.py:11
-#, fuzzy
-msgid "Server settings"
-msgstr "Impostazioni ManageSieve"
-
-#: extensions/radicale/app_settings.py:15
-#, fuzzy
-msgid "Server URL"
-msgstr "Porta del server"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr ""
-
-#: extensions/radicale/app_settings.py:24
-#, fuzzy
-msgid "Rights management"
-msgstr "Gestione quarantena"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:36
-#, fuzzy
-msgid "Allow calendars administration"
-msgstr "Amministratore di domini"
-
-#: extensions/radicale/app_settings.py:39
-#, fuzzy
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr ""
-"Numero massimo di amministratori di dominio che questo utente può creare"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr ""
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr ""
-
-#: extensions/radicale/forms.py:134
-#, fuzzy, python-format
-msgid "Mailbox %s does not exist"
-msgstr "Il dominio '%s' non esiste"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr ""
-
-#: extensions/radicale/forms.py:162
-#, fuzzy
-msgid "New calendar"
-msgstr "Nuovo alias"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-#, fuzzy
-msgid "Calendar created"
-msgstr "Filtro creato"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-#, fuzzy
-msgid "Calendar updated"
-msgstr "Profilo aggiornato"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr ""
-
-#: extensions/radicale/models.py:94
-#, fuzzy
-msgid "User"
-msgstr "Nome utente"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr ""
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-#, fuzzy
-msgid "Calendar removed"
-msgstr "Filtro eliminato"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr ""
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr ""
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr ""
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-#, fuzzy
-msgid "Add calendar"
-msgstr "Aggiungi alias"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr ""
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Plugin per creare facilmente filtri lato-server"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "Filtri Sieve"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Filtri messaggi"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "Impostazioni ManageSieve"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Indirizzo del tuo server MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "Porta di ascolto del tuo servere MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Connetti utilizzando STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Usa l'estensione STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Meccanismo di autenticazione"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Meccanismo di autenticazione preferito"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Modo editor"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Seleziona la modalità di lavoro che desideri per l'editor"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Seleziona per attivare questo insieme di filtri"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Tutti i seguenti"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Alcuni dei seguenti"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "contiene"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "non contiene"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "è"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "non è"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Mittente"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Destinatario"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Cc"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Dimensione"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "è maggiore di"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "è minore di"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Sposta il messaggio in"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Ridireziona il messaggio a"
-
-#: extensions/sievefilters/forms.py:110
-#, fuzzy
-msgid "Wrong filter name"
-msgstr "Nome del file"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr ""
-"Connessione al server MANAGESIEVE fallita, controlla la tua configurazione"
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Non c'è spazio sufficiente nel server"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Recupero delle impostazioni di filtro fallito"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Nuovo filtro"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filtro creato"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Modifica filtro"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filtro modificato"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filtro eliminato"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Rimozione del filtro fallita"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Gruppo filtri salvato"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Gruppo filtri creato"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Crea un nuovo gruppo di filtri"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Gruppo filtri eliminato"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Gruppo filtri attivato"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Condizioni"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Attivo"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Non ci sono ancora filtri definiti"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Impostazioni dei filtri"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "attivo"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr ""
-"Non è ancora stato definito alcun gruppo di filtri. Devi crearne uno per "
-"definire dei filtri"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Nuovo gruppo di filtri"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Salva il gruppo di filtri"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Attiva gruppo di filtri"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Elimina gruppo di filtri"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Download"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Elimina questo filtro"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Sposta questo filtro in alto"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Sposta questo filtro in basso "
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Grafico delle statistiche sul traffico e-mail utilizzando RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Grafico statistiche"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Percorso del file di log"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Percorso del file di log utilizzato per raccogliere le statistiche"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Cartella dei file RRD"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Percorso della cartella dove sono memorizzati i file RRD"
-
-#: extensions/stats/graphics.py:98
-#, fuzzy
-msgid "Average traffic (msgs/min)"
-msgstr "Dimensione del traffico normale medio"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "messaggi inviati"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "messaggi ricevuti"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "messaggi di rimbalzo"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "messaggi respinti"
-
-#: extensions/stats/graphics.py:112
-#, fuzzy
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Dimensione del traffico normale medio"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "dimensione di ricezione"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "dimensione di spedizione"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Traffico mail"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Non sono disponibili statistiche"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Giorno"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Settimana"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Mese"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Anno"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr ""
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Impostazione grafica sconosciuta"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Periodo personalizzato sbagliato"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Ricerca un dominio"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Applica"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Webmail IMAP semplice"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Dimensione massima degli allegati"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr ""
-"Dimensione massima degli allegati in bytes (o KB, MB, GB se specificato)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "Impostazioni IMAP"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Indirizzo del tuo server IMAP"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Usa una connessione sicura per accedere al server IMAP"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Porta di ascolto del tuo server IMAP"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "Impostazioni SMTP"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Indirizzo del tuo server SMTP"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Modalità di connessione sicura"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Nessuno"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Usa una connessione sicura per accedere al server SMTP"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Porta di ascolto del tuo server SMTP"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "È richiesta l'autenticazione"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "Il server richiede l'autenticazione"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Modalità di visualizzazione del messaggio predefinita"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr ""
-"La modalità di visualizzazione predefinita quando viene mostrato il messaggio"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Attiva la visualizzazione dei collegamenti HTML"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Attiva/Disattiva la visualizzazione dei collegamenti HTML"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Imposta il numero massimo di messaggi da visualizzare in una pagina"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Frequenza di aggiornamento dell'elenco"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Frequenza di aggiornamento automatico delle cartelle (in secondi)"
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr "Larghezza del contenitore delle caselle"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr "Larghezza della lista delle caselle"
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Cestino"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Cartella dove finiscono i messaggi eliminati"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Inviati"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Cartella dove finiscono le copie dei messaggi spediti"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Bozze"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Cartella dove finiscono le bozze"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Composizione messaggi"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Editor predefinito"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "L'editor predefinito da usare quando si scrive un messaggio"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Testo signature"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Signature delle e-mail personalizzato dall'utente"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr "Il valore dev'essere un intero positivo"
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Risposta del server"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Azione sconosciuta"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "Cci"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Webmail"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d messaggio cancellato"
-msgstr[1] "%(count)d messaggi cancellati"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Casella di posta vuota"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Casella di posta creata"
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Crea una nuova casella di posta"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Modifica casella di posta"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Casella di posta aggiornata"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Salvataggio allegato fallito: "
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "L'allegato è troppo grande (limite: %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Allegati"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Domanda sbagliata"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Rimozione allegato fallita: "
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Allegato sconosciuto"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "scritto:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Messaggio originale"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Impossibile recuperare il delimitatore delle gerarchie"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "Connessione al server IMAP fallita: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Allega"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Caricamento ..."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Casella di posta principale"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Rispondi"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Rispondi a tutti"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Mostra le opzioni"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Attiva i collegamenti"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Disabilita i collegamenti"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Invia"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-#, fuzzy
-msgid "Mark as read"
-msgstr "Contrassegna i messaggi"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-#, fuzzy
-msgid "Mark as unread"
-msgstr "Come non letti"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Svuota cartella"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Modifica la casella di posta selezionata"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Elimina la cartella di posta selezionata"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Comprimi cartella"
-
-#: lib/dbutils.py:36
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Messaggio inviato"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "La connessione con il database %s non è configurata"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Accesso negato: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Accesso negato"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr ""
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Richiesta non valida"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Inserisci un nome di dominio valido"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Si"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "No"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Aggiornamento della password fallito: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Utente semplice"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super amministratore"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Amministratore di domini"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Dispiace"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "La pagina richiesta non esiste"
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "È intervenuto un errore interno"
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Ricerca ..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Mittente"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Oggetto"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Entrambi"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Errore:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Aiuto"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Chiudi"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Precedente"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Successivo"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Benvenuti in Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Ricordami"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Registrati"
-
#, fuzzy
-#~ msgid "Server location"
-#~ msgstr "Porta del server"
-
-#~ msgid "Filter"
-#~ msgstr "Filtro"
-
-#~ msgid "Check requests interval"
-#~ msgstr "Intervallo di controllo delle request "
-
-#~ msgid "pending requests"
-#~ msgstr "richieste in sospeso"
-
-#~ msgid "Average normal traffic"
-#~ msgstr "Traffico normale medio"
-
-#~ msgid "msgs/min"
-#~ msgstr "msg/min"
-
-#~ msgid "Average bad traffic"
-#~ msgstr "Traffico maligno medio"
-
-#~ msgid "bytes/min"
-#~ msgstr "bytes/min"
-
-#~ msgid "Total"
-#~ msgstr "Totale"
-
-#~ msgid "Predefined time ranges"
-#~ msgstr "Intervalli di tempo predefiniti"
-
-#~ msgid "Custom time range"
-#~ msgstr "Intervallo di tempo personalizzato"
-
-#~ msgid "Add Cc field"
-#~ msgstr "Aggiungi campo Cc"
-
-#~ msgid "Add Cci field"
-#~ msgstr "Aggiungi campo Cci"
-
-#~ msgid "%(counter)s file"
-#~ msgid_plural "%(counter)s files"
-#~ msgstr[0] "%(counter)s file"
-#~ msgstr[1] "%(counter)s file"
-
-#~ msgid "Mailbox quota"
-#~ msgstr "Quota casella di posta"
-
-#~ msgid "Close this message"
-#~ msgstr "Chiudi questo messaggio"
-
-#~ msgid "New message"
-#~ msgstr "Nuovo messaggio"
-
-#~ msgid "Mark messages"
-#~ msgstr "Contrassegna i messaggi"
-
-#~ msgid "As read"
-#~ msgstr "Come letti"
-
-#~ msgid "No entries to display"
-#~ msgstr "Non ci sono elementi da mostrare"
-
-#~ msgid "activate"
-#~ msgstr "attiva"
-
-#~ msgid "Powered by Modoboa"
-#~ msgstr "Powered by Modoboa"
-
-#~ msgid "A domain %s already exists"
-#~ msgstr "Esiste già un dominio %s"
-
-#~ msgid "Directory to store PNG files"
-#~ msgstr "Cartella dei file PNG"
-
-#~ msgid "Path to directory where PNG files are stored"
-#~ msgstr "Percorso della cartella dove sono memorizzati i file PNG"
-
-#~ msgid "Failed to grant access (%s)"
-#~ msgstr "Accesso fallito (%s)"
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
diff --git a/modoboa/locale/it/LC_MESSAGES/djangojs.po b/modoboa/locale/it/LC_MESSAGES/djangojs.po
index 0a7b2a059..25a134486 100644
--- a/modoboa/locale/it/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/it/LC_MESSAGES/djangojs.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2013-12-23 00:58+0100\n"
"Last-Translator: Alberto Berti \n"
"Language-Team: Italiano \n"
@@ -16,177 +16,26 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "Non eliminare la cartella dei domini"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Questa operazione eliminerà TUTTI i dati associati a questo dominio."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr ""
-"Questa operazione eliminerà tutti i dati associati a questo dominio tranne "
-"gli account"
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Non è stato definito un amministratore di dominio"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Non eliminare la cartella della casella posta"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Rilasciare questa selezione?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Eliminare questa selezione?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-#, fuzzy
-msgid "Mark this selection as spam?"
-msgstr "Rilasciare questa selezione?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-#, fuzzy
-msgid "Mark this selection as non-spam?"
-msgstr "Rilasciare questa selezione?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Rilasciare questo messaggio?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Eliminare questo messaggio?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Visualizza tutte le intestazioni"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Nascondi le intestazioni"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr "Servizi aggiornati"
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr ""
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Rimuovere questo filtro?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Salvare le modifiche?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Rimuovere il gruppo di filtri?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Attivare il gruppo di filtri?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "attivo"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Cerca un dominio"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr ""
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Rimuovere la casella di posta selezionata?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Casella di posta rimossa"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Messaggio inviato"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "Spostato %s messaggio"
-msgstr[1] "Spostati %s messaggi"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Attenzione"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Elimina"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr "Errore interno"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr ""
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Ricerca"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Ricerca ..."
-
-#~ msgid "%s file"
-#~ msgid_plural "%s files"
-#~ msgstr[0] "%s file"
-#~ msgstr[1] "%s file"
+#, fuzzy
+#, fuzzy
diff --git a/modoboa/locale/nl_NL/LC_MESSAGES/django.po b/modoboa/locale/nl_NL/LC_MESSAGES/django.po
index f0279de98..eac909247 100644
--- a/modoboa/locale/nl_NL/LC_MESSAGES/django.po
+++ b/modoboa/locale/nl_NL/LC_MESSAGES/django.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Andrew , 2014
# TuxBrother , 2014
@@ -9,3092 +9,553 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2014-12-31 11:37+0000\n"
"Last-Translator: TuxBrother \n"
-"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/modoboa/language/nl_NL/)\n"
+"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/"
+"modoboa/language/nl_NL/)\n"
+"Language: nl_NL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: nl_NL\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Algemeen"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr "Er is een nieuwe versie van Modoboa beschikbaar!"
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Authenticatie"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Authenticatie type"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Lokaal"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "De backend gebruikt voor authenticatie"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Standaard wachtwoord encryptiemethode"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (zwak)"
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (zwak)"
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (zwak)"
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (zwak)"
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (onversleuteld!)"
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Schema dat gebruikt word om mailbox wachtwoorden te versleutelen"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr "Rondes"
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
-msgstr "Nummer van te gebruiken randomizeringsrondes (alleen bij sha256crypt en sha512crypt). Moet tussen de 1000 en 999999999 liggen."
-
-#: core/app_settings.py:75
+msgstr ""
+"Nummer van te gebruiken randomizeringsrondes (alleen bij sha256crypt en "
+"sha512crypt). Moet tussen de 1000 en 999999999 liggen."
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Geheime sleutel"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Code die gebruikt word om wachtwoorden te versleutelen/ontsleutelen"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "LDAP instellingen"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Server adres"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "Het IP adres en de DNS naam van LDAP server"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Server poort"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Het TCP poortnummer gebruikt door de LDAP server"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Gebruik een beveiligde verbinding"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Gebruik een SSL/TLS verbinding met de LDAP server"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Authenticatie methode"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Zoeken en koppelen"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Directe koppeling"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Kies een authenticatie methode om te gebruiken"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Koppeling DN"
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
-msgstr "De gedistingeerde naam om te gebruiken bij het koppeling met de LDAP server. Laat leeg voor een anonieme koppeling."
-
-#: core/app_settings.py:127
+msgstr ""
+"De gedistingeerde naam om te gebruiken bij het koppeling met de LDAP server. "
+"Laat leeg voor een anonieme koppeling."
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Koppel wachtwoord"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
-msgstr "Het wachtwoord om te gebruiken tijdens het koppelen met de LDAP server (met 'koppel DN')"
-
-#: core/app_settings.py:139
+msgstr ""
+"Het wachtwoord om te gebruiken tijdens het koppelen met de LDAP server (met "
+"'koppel DN')"
+#: core/app_settings.py:134
msgid "Users search base"
msgstr "Gebruikers zoekbasis"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "De gedistingeerde naam van de zoekbasis om gebruikers te vinden"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Zoek filter"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
-msgstr "Een optionele filter string (zoals '(objectClass=person)'). Om geldig te kunnen zijn, moet het ingesloten zijn tussen haakjes."
-
-#: core/app_settings.py:160
+msgstr ""
+"Een optionele filter string (zoals '(objectClass=person)'). Om geldig te "
+"kunnen zijn, moet het ingesloten zijn tussen haakjes."
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Gebruiker DN template"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
"placeholder (ie. %(user)s)"
-msgstr "Het template dat gebruikt word om een gebruiker zijn/haar DN op te bouwen. Het moet een placeholder bevatten (bijvoorbeeld. %(user)s)"
-
-#: core/app_settings.py:171
+msgstr ""
+"Het template dat gebruikt word om een gebruiker zijn/haar DN op te bouwen. "
+"Het moet een placeholder bevatten (bijvoorbeeld. %(user)s)"
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Wachtwoord attribuut"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Dit attribuut word gebruikt om wachtwoorden op te slaan"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "De LDAP server is een Active Directory"
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Administrator groepen"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
-"Members of those LDAP Posix groups will be created as domain administrators."
-" Use ';' characters to separate groups."
-msgstr "Leden van deze LDAP POSIX groepen zullen aangemaakt worden als domein administrators. Gebruik ';' karakters om groepen te scheiden."
-
-#: core/app_settings.py:195
+"Members of those LDAP Posix groups will be created as domain administrators. "
+"Use ';' characters to separate groups."
+msgstr ""
+"Leden van deze LDAP POSIX groepen zullen aangemaakt worden als domein "
+"administrators. Gebruik ';' karakters om groepen te scheiden."
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Groepen zoek basis"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "De gedistingeerde naam van de zoekbasis om groepen te vinden"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Diversen"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Top notificaties controle interval"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Interval tussen twee top notificatie checks"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Controleer of er een nieuwe versie beschikbaar is"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Automatische controle voor nieuwe versies"
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Maximum bewaartijd van logs"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "De maximum bewaartijd in dagen van een log record"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Items per pagina"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Hoeveelheid items per pagina"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Standaard top omleiding"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
-msgstr "De standaard omleiding die gebruikt word als er geen andere applicatie is opgegeven"
-
-#: core/app_settings.py:268
+msgstr ""
+"De standaard omleiding die gebruikt word als er geen andere applicatie is "
+"opgegeven"
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Sleutelwaarde moet 16, 24 of 32 bytes lang zijn"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Ongeldige zinsbouw"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Ongeldig nummer van rondes"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Dit veld is benodigd"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Weergeven"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Voorkeurs taal"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Voorkeurstaal om pagina's weer te geven"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Gebruikersnaam"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Wachtwoord"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Oud wachtwoord"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Nieuw wachtwoord"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Bevestiging"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Oud wachtwoord komt niet overeen"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Wachtwoorden komt niet overeen"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr "wachtwoord"
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr "laatste login"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "U kunt uw eigen account niet verwijderen"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Mislukt om wachtwoord aan te passen: LDAP module niet geinstalleerd"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "account"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Verkeerde regel"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "U kunt geen accounts importeren met hogere rechten dan die van uzelf."
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "De gebruiker '%s' moet een geldig email adres hebben"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "gebruikersnaam en email velden moeten niet verschillen van '%s'"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "actief"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Aanvinken om deze extensie te activeren"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "toegevoegd"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "veranderd"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s door gebruiker %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "verwijderd"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Extensies"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Kies de extensie(s) om te gebruiken"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Naam"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Versie"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Beschrijving"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Opslaan"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Informatie"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informatie over Modoboa"
-
#: core/templates/core/information.html:5
msgid "An update is available!"
msgstr "Er is een update beschikbaar!"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
"\n"
-" Modoboa %(version)s is available for download. The list of all changes is available here .\n"
+" Modoboa %(version)s is available for download. The list "
+"of all changes is available here .\n"
" "
-msgstr "\nModoboa %(version)s is beschikbaar om te downloaden. De lijst met alle veranderingen is hier beschikbaar."
-
+msgstr ""
+"\n"
+"Modoboa %(version)s is beschikbaar om te downloaden. De "
+"lijst met alle veranderingen is hier beschikbaar."
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "is momenteel in gebruik."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Actieve gebruikers"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Groep naam"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Laatste login"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Logs"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Vorige gebeurtenissen op Modoboa..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Datum"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Niveau"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Bericht"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Parameters"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configureer Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Opslaan"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Instellingen van Modoboa"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Instellingen"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Voorkeuren"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Modoboa aanpassen"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Profiel"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Persoonlijke informatie aanpassen"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Toepassen"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Uitloggen"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Parameters opgeslagen"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Wijzigingen toegepast."
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Gebruiker '%s' successvol aangemeld"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
-msgstr "Uw gebruikersnaam en wachtwoord komen niet overeen. Probeer het alstublief opnieuw."
-
-#: core/views/auth.py:72
+msgstr ""
+"Uw gebruikersnaam en wachtwoord komen niet overeen. Probeer het alstublief "
+"opnieuw."
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Gebruiker '%s' heeft afgemeld"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profiel aangepast"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Voorkeuren opgeslagen"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Testberichten"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Verstuur virus"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Verstuur spam"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Bericht verstuurd"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
"Welcome to the online demo! \n"
"Warning: the demo's concent is resetted every two hours.
\n"
-"To try the demo, the following users are available (username/password ):
\n"
+"To try the demo, the following users are available (username/password"
+"i>):
\n"
"\n"
" A super administrator : admin/password \n"
" A domain administrator : admin@demo.local/admin \n"
" A simple user : user@demo.local/user \n"
" \n"
"Please report any issue or give any suggestion to \n"
-" the mailing list .
\n"
-msgstr "\nWelkom in de online demo! \nWaarschuwing: de content van de demo word elke 2 uur gewist.
\nOm de demo te proberen, zijn de volgende gebruikers beschikbaar (gebruikersnaam/wachtwoord ):
\n\nDe hoofdbeheerder : admin/password \nDe domein administrator : admin@demo.local/admin \nEen gewone gebruiker : user@demo.local/user \n \nAarzel niet om problemen of suggesties door te geven aan \nde maillijst .
\nFouten gevonden in de Nederlandse vertaling? Geef uw opmerkingen of suggesties door aan: foss at waut punt nl
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Administratie console"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Web gebaseerde interface om domeinen, accounts en aliasen te beheren"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr "Administratie"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Domeinen"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Identiteiten"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Doorsturen"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Accounts importeren mislukt (%s): domein bestaat niet"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "Mailbox %s bestaat al"
-
-#: extensions/admin/__init__.py:186
-#, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Account import is mislukt (%s): verkeerd quotum waarde"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr "domein alias"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Mailboxen"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Pas mailboxen op het bestandssysteem aan"
-
-#: extensions/admin/app_settings.py:19
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr "Hernoem of verwijder mailboxen op het bestandssysteem wanner ze hernoemd of verwijderd worden in Modoboa."
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Eigenaar van de mailboxen"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "De UNIX account die de rechten heeft tot de mailboxen op het bestandssysteem"
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr "Standaard domein quota"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr "Standaard quota (in MB) om op nieuw aangemaakte domeinen zonder waarde toe te passen. Een waarde van 0 betekend geen quota."
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Automatish een account verwijderen"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr "Als een mailbox word verwijderd, verwijder dan ook de bijbehorende account"
-
-#: extensions/admin/app_settings.py:49
-msgid "Automatic domain/mailbox creation"
-msgstr "Domein en mailbox automatisch aanmaken"
-
-#: extensions/admin/app_settings.py:52
-msgid ""
-"Create a domain and a mailbox when an account is automatically created."
-msgstr "Maak een domein en mailbox aan wanneer een account automatisch is aangemaakt."
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr "Dit moet een positive integer zijn."
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr "Een mailbox is benodigd"
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr "De naam van de gebruiker. Moet een geldig e-mail adres zijn voor gebruikers of administrators met een mailbox."
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Regel"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Kiezen"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Welk niveau van rechten deze gebruiker zal hebben"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Herhaal wachtwoord (voor verificatie)"
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Actief"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "De wachtwoorden komen niet overeen."
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "U kunt uw eigen account niet uitschakelen"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "E-mail"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Quota"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr "Quota in MB voor deze mailbox. Geef een aangepaste waarde of gebruik de stanaard waarde van het domein. Laat leeg om een ongelimiteerde waarde te definieren (niet toegestaan voor domein administrators)."
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Alias(sen)"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr "Alias(en) van deze mailbox. Geef slechts een adres per regel op, en toets ENTER om een nieuwe regel te krijgen. Gebruik een wildcard '*' om een 'catch-all' adres te maken (bijvoorbeeld: *@domein.tld)."
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "Domein bestaat niet"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Domein(en)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Domein(en) die gebruiker mag beheren"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Mail"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Rechten"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Account aangepast"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Nieuwe account"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Account aangemaakt"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "Email adres"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr "Het adres van de distributielijst . Gebruik een wildcard '*' om een 'catch-all' adres te maken (bijvoorbeeld: *@domein.tld)"
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Ontvangers"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr "Mailbox(en) waarnaar deze alias zal verwijzen. Geef slechts een adres per regel op, en toets ENTER om een nieuwe regel te krijgen."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "U heeft geen toegang tot dit domein"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Verkeerde mailbox"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Lokale ontvanger %s niet gevonden"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "Ontvanger %s is al aanwezig"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Geen ontvanger opgegeven"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr "Standaard quota in MB toegepast op mailboxen. Laat leeg om de standaard waarde te gebruiken."
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr "Alias(sen) van dit domein. Geef slechts een adres per regel op, en toets ENTER om een nieuwe regel te krijgen."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr "Een %s met deze naam bestaat al"
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr "domein"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Maak een domein administrator aan"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Automatisch een administrator aanmaken voor dit domein"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr "De naam van de administrator. De domeinnaam word automatisch toegevoegd."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Aliassen aanmaken"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Automatisch een standaard alias voor dit domein aanmaken"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Verkeerd formaat"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "Gebruiker '%s' bestaat al"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Domein gewijzigd"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Opties"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Nieuw domein"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Domein aangemaakt"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Bestandsnaam"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Scheidingsteken"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Ontvanger(s)"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Geef een of meer ontvangers op, gescheiden door een komma"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Lokale kopie behouden"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr "Stuur berichten door en sla een kopie op in uw mailbox"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr "U kunt mail niet doorsturen naar een lokaal adres. Vraag uw systeembeheerder om een alias voor u aan te maken."
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Bestand selecteren"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Doorgaan als er een fout optreed"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Zie duplicaten niet als fout"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Versleutel wachtwoorden"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr "Vink deze optie aan als wachtwoorden in uw bestand niet versleuteld zijn"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "adres"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just"
-" enter an * character."
-msgstr "Het alias adres (zonder het domein deel). Voor een 'catch-all' adres, vul een * in."
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "mailboxen"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "De mailbox waarnaar deze alias verwijst"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Deze aliassen waarnaar deze alias verwijst"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Aanvinken om deze alias te activeren"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "distributie lijst"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "doorsturen"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Ongeldige regel: %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "Domein '%s' bestaat niet"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "naam"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "De domeinnaam"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Aanvinken om dit domein te activeren"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr "Domein"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr "Verkeerde quota waarde voor domein '%s'"
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "De alias naam"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "doel"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "De domein alias verwijst naar"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Onbekend domein %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Mailbox adres (zonder het @domein.naam deel)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Mislukt om de mailbox locatie te verkijgen (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "Quota is groter dan de maximaal toegestane domein limiet (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "Een quota is vereist"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-msgid "Domain is disabled"
-msgstr "Domein is gedeactiveerd"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "MB"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr "U kunt geen nieuwe domein administrator aanmaken"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Statistieken"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-msgid "Domains and identities"
-msgstr "Domeinen en identiteiten"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr "Globale statistieken"
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr "Type"
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-msgid "Quantity"
-msgstr "Hoeveelheid"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Domein aliassen"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr "Statistieken per domein"
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Labels"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Acties"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-msgid "disabled"
-msgstr "uitgeschakeld"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Administrators"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "Geen domein administrator toegewezen"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Datum van aanmaken"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Laatst gewijzigd"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Mailbox aliassen"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Automatisch mails doorsturen naar een ander adres"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Volledige naam/Ontvanger"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Help"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Importeren..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Kies een waarde"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Gebruik de standaard waarde van dit domein"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Adres"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Waarde"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Limiet"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Gebruik (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Zoeken"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "geactiveerd_m"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "geactiveerd_f"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-msgid "List domains"
-msgstr "Weergeef domeinen"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Domein toevoegen"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Importeren"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Exporteren"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Weergeef identiteiten"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Weergeef quota's"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Account aanmaken"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Alias toevoegen"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Doorsuurregel toevoegen"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Distributielijst toevoegen"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Weergeef de identiteiten van dit domein"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "Verwijder %s?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Deze bevoegdheid verwijderen"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Een alias met deze naam bestaat al"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Aanmaken"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Nieuwe distributie lijst"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Distributielijst aangemaakt"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Nieuwe alias"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias aangemaakt"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Nieuwe doorstuurregel"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Doorstuurregel aangemaakt"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Distributielijst aangepast"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Doorstuurregel aangepast"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Alias aangepast"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "U kunt uw eigen domein niet verwijderen"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Domeinen verwijderd"
-msgstr[1] "Domeinen verwijderd"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Identiteiten exporteren"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Exporteer domeinen"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Ongeldig verzoek"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Account verwijderd"
-msgstr[1] "Accounts verwijderd"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
+" the "
+"mailing list .\n"
+msgstr ""
+"\n"
+"Welkom in de online demo! \n"
+"Waarschuwing: de content van de demo word elke 2 uur gewist.
\n"
+"Om de demo te proberen, zijn de volgende gebruikers beschikbaar "
+"(gebruikersnaam/wachtwoord ):
\n"
"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
+"De hoofdbeheerder : admin/password \n"
+"De domein administrator : admin@demo.local/admin \n"
+"Een gewone gebruiker : user@demo.local/user \n"
" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr "Lever een CSV bestand en zorg dat de regels voldoen aan een van de volgende formaten:\n\ndomain; name; quota; enabled \ndomainalias; name; targeted domain; enabled \n%s\n \nHet eerste element van elke regel is verplicht en moet gelijk zijn aan een van de vorige waarden.
\nU kunt een eigen scheidingsteken gebruiken.
\nLet op! Zorg dat het 'line-encoding format' Unix is - anders gaat het importeren mis
\n\n"
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Importeer domeinen"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "Object bestaat al: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d objecten successvol geimporteerd"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr "Lever een CSV bestand en zorg dat de regels voldoen aan een van de volgende formaten:\n\naccount; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...] \nalias; address; enabled; internal recipient \nforward; address; enabled; external recipient \ndlist; address; enabled; recipient; recipient; ... \n \nHet eerste element van elke regel is verplicht en moet gelijk zijn aan een van de vorige waarden.
\nU kunt een eigen scheidingsteken gebruiken.
\nLet op! Zorg dat het 'line-encoding format' Unix is - anders gaat het importeren mis
\n"
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Identiteiten importeren"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Doorstuuradres aangepast"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Gemakkelijke amavis beheertool"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Quarantaine"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Quarantaine instellingen"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Maximum bericht bewaartijd"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr "Maximum bewaartijd quarantaine berichten (in dagen) voordat ze verwijderd worden"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Berichten worden vrijgegeven"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Verwijderde vrijgegeven berichten"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr "Verwijder berichten gemarkeerd als vrijgegeven tijdens het opruimen van de database"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Modus om met Amavis te verbinden"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Mode die gebruikt word om met de PDP server te verbinden"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "PDP server adres"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "PDP server adres (indien inet mode gebruikt word)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "PDP server poort"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "PDP server poort (indien inet mode gebruikt word)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "PDP server socket"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Locatie naar de PDP server socket (indien unix socket mode gebruikt word)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Sta toe om direct vrij te geven"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Sta een gebruiker to om zelf berichten vrij te geven"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Activeer de 'zelfbedienings' mode"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Activeer de 'zelfbedienings' mode"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Afzender van notificaties"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "E-mail adres dat gebruikt word om notificaties te versturen"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr "Handmatig leren"
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr "Handmatig leren inschakelen"
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr "Sta super administrators toe om SpamAssasin handmatig te trainen"
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr "Is SpamAssisin lokaal geïnstalleerd?"
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr "Draait SpamAssasin op dezelfde server als Modoboa?"
-
-#: extensions/amavis/app_settings.py:99
-msgid "Default user"
-msgstr "Standaard gebruiker"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr "Naam van de systeemgebruiker die rechten over de 'bayesian database' heeft"
-
-#: extensions/amavis/app_settings.py:107
-msgid "Spamd address"
-msgstr "Spamd adres"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr "Het IP adres waar spamd beschikbaar is"
-
-#: extensions/amavis/app_settings.py:113
-msgid "Spamd port"
-msgstr "Spamd poort"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr "De TCP-poort waar spamd naar luistert"
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr "Zet per-domein handmatig leren aan"
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr "Sta domein administrators toe om SpamAssassin te trainen (binnen losstaande databases per domein)"
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr "Zet handmatig leren per-gebruiker aan"
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr "Sta simpele gebruikers toe om zelf SpamAssasin te trainen (binnen een losstaande database)"
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Aantal weergegeven emails per pagina"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Stelt het maximum aantal weergegeven berichten per pagina in"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr "Globale database"
-
-#: extensions/amavis/forms.py:94
-msgid "Domain's database"
-msgstr "Database van domein"
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr "Database van gebruiker"
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr "Openstaande verzoeken"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Content filter"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "Verbinding met amavis mislukt: %s"
-
-#: extensions/amavis/lib.py:131
-msgid "No recipient found"
-msgstr "Geen geaddresseerde gevonden"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Virus filter"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "ja"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "nee"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "standaard"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr "Optie om virusscans over te slaan. Kies 'default' om de systeeminstelling te gebruiken."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Spam filter"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr "Optie om spamfilter over te slaan. Kies 'default' om de systeeminstelling te gebruiken."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Zwarte lijst"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr "Optie om zwarte lijst over te slaan. Kies 'default' om de systeeminstelling te gebruiken."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Spam indicator"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global"
-" settings."
-msgstr "Wijzig standaard spam voorvoegsel met de opgegeven text. Kies 'default' om de systeeminstelling te gebruiken. Geef niets op als u geen voorvoegsel wilt."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Niets in quarantaine"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Bericht verwijderd"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d bericht successvol verwijderd"
-msgstr[1] "%(count)d berichten successvol verwijderd"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Verzoek ingediend"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Bericht vrijgegeven"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d verzoek ingediend"
-msgstr[1] "%(count)d verzoeken ingediend"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d bericht successvol vrijgegeven"
-msgstr[1] "%(count)d berichten successvol vrijgegeven"
-
-#: extensions/amavis/views.py:360
-#, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d bericht succesvol verwerkt"
-msgstr[1] "%(count)d berichten succesvol verwerkt"
-
-#: extensions/amavis/views.py:394
-msgid "Select a database"
-msgstr "Selecteer een database"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr "Valideer"
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Openstaand quarantaine vrijgeef verzoek"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Drempels"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "of meer is spam"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "of meer weiger bericht"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr "Score"
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "Naar"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "Van"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Onderwerp"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-msgid "Released"
-msgstr "Vrijgegeven"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-msgid "Marked as spam"
-msgstr "Gemarkeerd als ongewenst"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-msgid "Marked as non-spam"
-msgstr "Gemarkeerd als gewenst"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Quarantaine beheer"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr "Selecteren"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr "Schoon"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Ongewenst"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr "Ongeldige Header"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Verkeerde MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr "Geband"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Vrijgeven"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Verwijderen"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-msgid "Mark as spam"
-msgstr "Markeer als ongewenst"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr "Markeer als gewenst"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Alle berichten"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr "Alles"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr "Alleen schoon"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr "Alleen spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr "Alleen virussen"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr "Alleen ongeldige headers"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr "Alleen ongeldige MIME's"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr "Alleen geband"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] "\n%(counter)s vrijgeef verzoek ingediend.\n"
-msgstr[1] "\n%(counter)s vrijgeef verzoeken ingediend.\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Voorbeeld:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "Van:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "Naar:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Datum:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Onderwerp:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Reageer op dit bericht:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Bezoek %(listingurl)s voor een volledige lijst."
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Terug"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Volledige headers weergeven"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr "Administrators limiteren in de hoeveelheid objecten die ze kunnen aanmaken"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Limieten"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Standaard limieten"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Domein administrators"
-
-#: extensions/limits/app_settings.py:15
-msgid ""
-"Maximum number of allowed domain administrators for a new administrator"
-msgstr "Maximum aantal toegestane domein administrators voor een nieuwe administrator"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Maximum aantal toegestane domeinen voor een nieuwe administrator"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr "Maximum aantal domein aliassen voor een nieuwe administrator"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Maximum aantal toegestane mailboxen voor een nieuwe administrator"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Maximum aantal aliassen voor een nieuwe administrator"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Ongeldige limiet"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Uw capaciteiten zijn nog niet geintialiseerd"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "U mag geen ongelimiteerde waardes opgeven"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Verkoper"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Capaciteiten"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s: limiet bereikt"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Niet genoeg capaciteit"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr "Maximum aantal domein administrators die deze gebruiker aan kan maken"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Maximum aantal domeinen die deze gebruiker aan kan maken"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Maximum aantal domein-aliassen die deze gebruiker kan aanmaken"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Maximum aantal mailboxen die deze gebruiker kan aanmaken"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr "Maximum mailbox aliassen die deze gebruiker kan aanmken"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "ongedefinieerd"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "ongelimiteerd"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Capaciteit gebruik"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Auto-antwoord (vakantiebericht) functionaliteit dmv. Postfix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Automatisch antwoorden"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Automatisch antwoorden timeout"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr "Timeout in seconden tussen twee auto-antwoorden naar dezelfde afzender"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr "Standaard onderwerp"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr "Ik ben niet aanwezig"
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr "Standaard onderwerp gebruikt wanneer een automatisch antwoord automatisch is aangemaakt"
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr "Standaard inhoud"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr "Momenteel ben ik niet aanwezig. Ik zal antwoorden zodra ik terug kom.\n\nMet vriendelijke groet,\n%(name)s\n"
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr "Standaard inhoud gebruikt wanneer een automatisch antwoord bericht automatisch is aangemaakt. De '%(name)s' macro zal vervangen worden door de naam van de gebruiker."
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr "Activeer uw auto-antwoord vanaf deze datum"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Tot"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Activeer uw auto-antwoord tot deze datum"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Deze datum is over"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr "De datum moet in de toekomst vanaf de startdatum liggen"
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Auto-antwoord bericht"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr "Activeer auto-antwoord"
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr "Activeer of Deactiveer Postfix auto-antwoord"
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "onderwerp"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "Het onderwerp dat zal verschijnen in verstuurde mails"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "inhoud"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "De inhoud die zal verschijnen in versuurde mails"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Activeer/Deactiveer uw auto-antwoord"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Auto antwoord bericht successvol aangepast."
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr "Maak een bericht dat automatisch verstuurd word wanneer u niet aanwezig bent"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr "Activeer doorstuur domeinen ondersteuning voor Postfix"
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr "Doorstuur domeinen"
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr "Map waarin Postfix's master.cf staat"
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr "Locatie van Postfix's master.cf"
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr "Alias(sen) van dit doorstuur domein. Geef slechts een adres per regel op, en toets ENTER om een nieuwe regel te krijgen."
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr "doorstuur domein alias"
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr "doorstuur domein"
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr "Doorstuur domein aangepast"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr "Doorstuur domein toevoegen"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr "Maximum aantal doorstuur domeinen die deze gebruiker aan kan maken"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr "Doorstuur domein aliassen"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr "Maximum aantal van doorstuur domeinen die deze gebruiker aan kan maken"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr "\nrelaydomain; name; target host; service; enabled; verify recipients \nrelaydomainalias; name; target; enabled \n"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr "Maximum aantal toegestane doorstuur domeinen voor een nieuwe administrator"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr "Maximum aantal doorstuur domein aliassen voor een nieuwe administrator"
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr "De servicenaam"
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr "doel host"
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr "Externe bestemming van dit domein"
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr "controleer ontvangers"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr "Controleer geldigheid ontvangers"
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr "Doorstuur Domein"
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr "Het doorstuur domein verwijst naar"
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr "Doorstuur domein %s bestaat niet"
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr "Doorstuur domein aangemaakt"
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr "Nieuw doorstuur domein"
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr "Doorstuur domein verwijderd"
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr "Scan"
-
-#: extensions/radicale/__init__.py:34
-msgid "Radicale management"
-msgstr "Radicale beheer"
-
-#: extensions/radicale/__init__.py:38
-msgid ""
-"Management frontend for Radicale, a simple calendar and contact server."
-msgstr "Beheermodule voor Radicale, een simpele server kalenders en contacten."
-
-#: extensions/radicale/app_settings.py:11
-msgid "Server settings"
-msgstr "Server instellingen"
-
-#: extensions/radicale/app_settings.py:15
-msgid "Server URL"
-msgstr "Server URL"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr "De URL van de Radicale server. Het zal gebruikt worden om kalender URL's samen te stellen."
-
-#: extensions/radicale/app_settings.py:24
-msgid "Rights management"
-msgstr "Rechten beheer"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr "Locatie van het rechtenbestand"
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr "Locatie van het bestand dat de rechtendefinitie bevat"
-
-#: extensions/radicale/app_settings.py:36
-msgid "Allow calendars administration"
-msgstr "Sta het beheer van kalenders toe"
-
-#: extensions/radicale/app_settings.py:39
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr "Sta domein administrators toe om kalenders van gebruikers te beheren (lezen en schrijven)"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr "Lezen"
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr "Schrijven"
-
-#: extensions/radicale/forms.py:134
-#, python-format
-msgid "Mailbox %s does not exist"
-msgstr "Mailbox %s bestaat niet"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr "Rechten"
-
-#: extensions/radicale/forms.py:162
-msgid "New calendar"
-msgstr "Nieuwe kalender"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-msgid "Calendar created"
-msgstr "Kalender aangemaakt"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-msgid "Calendar updated"
-msgstr "Kalender bijgewerkt"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr "Kalenders"
-
-#: extensions/radicale/models.py:94
-msgid "User"
-msgstr "Gebruiker"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr "Gedeeld"
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-msgid "Calendar removed"
-msgstr "Kalender verwijderd"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr "Nieuwe gedeelde kalender"
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr "Versturen"
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr "Deze kalender heeft het volgende adres:"
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr "Eigenaar"
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-msgid "Add calendar"
-msgstr "Kalender toevoegen"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr "Gedeelde kalender toevoegen"
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr "Laat de kalender details zien"
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr "Bewerk %s"
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Plugin om gemakkelijk filters op de server in te stellen (bijvoorbeeld om uw mail te sorteren)"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "Sieve filters"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Berichtfilters"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "ManageSieve instellingen"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Adres van uw MANAGESIEVE server"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "Poort van uw MANAGESIEVE server"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Verbind dmv. STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Gebruik de STARTTLS extensie (aanbevolen)"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Authenticatie mechanisme"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Geprefereerde authenticatie mechanisme"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Editor mode"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Selecteer de mode waarin u de editor wilt hebben"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Aanvinken om deze filterset te activeren"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Alles van de volgende"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Elke van het volgende"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "bevat"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "bevat niet"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "is"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "is niet"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Afzender"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Ontvanger"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "CC"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Grootte"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "is groter dan"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "is minder dan"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Verplaats bericht naar"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Bericht doorsturen naar"
-
-#: extensions/sievefilters/forms.py:110
-msgid "Wrong filter name"
-msgstr "Verkeerde filter naam"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr "Verbinding naar MANAGESIEVE server mislukt, controleer uw configuratie"
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Niet genoeg ruimte beschikbaar op de server"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Mislukt om de filterset te te laden"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Nieuw filter"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filter aangemaakt"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Filter bewerken"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filter aangepast"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filter verwijderd"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Mislukt om het filter te verwijderen"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Filterset opgeslagen"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Filterset aangemaakt"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Maak een nieuwe filterset aan"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Filterset verwijderd"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Filterset geactiveerd"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Voorwaarden"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Actief"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Nog geen filter aangemaakt"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Filtersets"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "actief"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr "Nog geen filterset gedefinieerd. U moet een filterset aanmaken om filters in te kunnen stellen."
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Nieuwe filterset"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Filterset opslaan"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Filterset activeren"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Filterset verwijderen"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Download"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Dit filter verwijderen"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Dit filter omhoogplaatsen"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Dit filter omlaagplaatsen"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Grafische statistieken over emailverkeer dmv. RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Grafische statistieken"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Locatie van logbestand"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Locatie van logbestand gebruik om statistieken te maken"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Map om RRD bestanden op te slaan"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Locatie van map waar RRD bestanden staan"
-
-#: extensions/stats/graphics.py:98
-msgid "Average traffic (msgs/min)"
-msgstr "Gemiddeld verkeer per minuut (berichten)"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "verstuurde berichten"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "ontvangen berichten"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "geweigerde berichten"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "geweigerde berichten"
-
-#: extensions/stats/graphics.py:112
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Gemiddelde bandbreette per minuut (bytes)"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "ontvangen grootte"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "verstuurde grootte"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Mailverkeer"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Geen statistieken beschikbaar"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Dag"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Week"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Maand"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Jaar"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr "Aangepast"
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Onbekende grafische set"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Ongeldige aangepaste periode"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Zoek een domein"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Toepassen"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Simpele IMAP webmail"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Maximum grootte van bijlage"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Maximum grootte van een bijlage in bytes (of KB, MB, GB als opgegeven)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "IMAP instellingen"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Adres van uw IMAP server"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Gebruik een beveiligde verbinding met de IMAP server (aanbevolen)"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Poort van uw IMAP server"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "SMTP instellingen"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Adres van uw IMAP server"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Beveiligde verbinding gebruiken"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Geen"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Gebruik een beveiligde verbinding met de SMTP server (aanbevolen)"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Poort van de SMTP server"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Authenticatie vereist"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "De server vereist authenticatie"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Standaard bericht weergave"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "De standaard mode wanneer een bericht weergegeven wordt"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Activeer HTML links scherm"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Zet het weergeven van HTML links aan of uit"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Stelt het maximum aantal weergegeven berichten per pagina in"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Lijst automatisch vernieuwen"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Map automatisch vernieuwen (in seconden)"
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr "Breedte van de mailbox container"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr "De breedte van de mailbox lijst container"
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Prullenbak"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Map voor verwijderde berichten"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Verstuurd"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Map waar verzonden berichten worden opgeslagen"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Concepten"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Map waar concepten heen gaan"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Berichten opstellen"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Standaard editor"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "De standaard editor voor het schrijven van een bericht"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Handtekening text"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Gebruiker opgegeven email handtekening"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr "Waarde moet een positieve integer zijn (>0)"
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Antwoord van server"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Onbekende actie"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "BCc"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Webmail"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d bericht verwijderd"
-msgstr[1] "%(count)d berichten verwijderd"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Mailbox leegmaken"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Mailbox aangemaakt"
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Nieuwe mailbox aanmaken"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Wijzing mailbox"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Mailbox aangepast"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Mislukt om deze bijlage(s) op te slaan:"
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "Bijlage is te groot (maximaal toegestane grootte: %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Bijlagen"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Verkeerde query"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Mislukt om bijlage te verwijderen:"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Onbekende bijlage"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "schreef:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Oorspronkelijk bericht"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Mislukt om de hiërarchische scheiding te verkrijgen"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "Verbinding met de IMAP server mislukt: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Bijvoegen"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Uploaden.."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Hoofd mailbox"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr "Samenstellen"
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Antwoorden"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Allen antwoorden"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Weergave opties"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Activeer links"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Links uitschakelen"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Versturen"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-msgid "Mark as read"
-msgstr "Markeer als gelezen"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-msgid "Mark as unread"
-msgstr "Markeer als ongelezen"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Lege map"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Bewerk geselecteerde mailbox"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Verwijder geselecteerde mailbox"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Comprimeer map"
-
-#: lib/dbutils.py:36
+"Aarzel niet om problemen of suggesties door te geven aan \n"
+"de "
+"maillijst .
\n"
+"Fouten gevonden in de Nederlandse vertaling? Geef uw opmerkingen of "
+"suggesties door aan: foss at waut punt nl
\n"
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Bericht verstuurd"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Verbinding naar database %s niet ingesteld"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Toegang geweigerd: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Toegang geweigerd"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr "Versturen"
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Ongeldig verzoek"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Vul een geledige domeinnaam in"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Ja"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "Nee"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Mislukt om wachtwoord aan te passen: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Gebruiker"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Hoofdbeheerder"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Domein administrator"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Sorry"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "De opgegeven pagina bestaat niet."
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Er is een interne fout opgetreden."
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Zoeken..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Van adres"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Onderwerp"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Beiden"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Foutmelding:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Help:"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Sluiten"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Vorige"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Volgende"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Welkom bij Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Onthoud mij"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Inloggen"
diff --git a/modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po b/modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po
index 85eb7eef8..d0300f3e7 100644
--- a/modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# TuxBrother , 2014
# TuxBrother , 2014
@@ -9,177 +9,34 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2014-12-31 11:42+0000\n"
"Last-Translator: TuxBrother \n"
-"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/modoboa/language/nl_NL/)\n"
+"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/"
+"modoboa/language/nl_NL/)\n"
+"Language: nl_NL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: nl_NL\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Geen log bericht meer om te weergeven"
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr "Geen domein meer om te weergeven"
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "De map van dit domein niet verwijderen (Zal de data ervan behouden)"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Deze actie zal ALLE data verwijderen die bij dit domein hoort. Wilt u doorgaan?"
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr "Deze actie zal alle data die bij dit domein hoort verwijderen, behalve de gebruikers."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Geen administrator toegewezen"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr "Geen identiteiten meer om te weergeven"
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Verwijder de map van deze mailbox niet (zal de data ervan behouden)"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr "Geen quota meer om te weergeven"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr "Geen berichten meer om te weergeven"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Wilt u deze selectie loslaten?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Selectie verwijderen?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-msgid "Mark this selection as spam?"
-msgstr "Markeer deze selectie als ongewenst?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-msgid "Mark this selection as non-spam?"
-msgstr "Markeer deze selectie als gewenst?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Dit bericht loslaten?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Dit bericht verwijderen?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr "Markeer als ongewenst?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr "Markeer als gewenst?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Volledige headers weergeven"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Volledige headers verbergen"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr "Services upgedate"
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr "Geen kalenders meer om te weergeven"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Dit filter verwijderen?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Wijzigingen opslaan?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Deze filterset verwijderen?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Wilt u deze filterset activeren?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "activeren"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Zoek een domein"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr "Geen berichten meer in deze mailbox."
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Geselecteerde mailbox verwijderen?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Mailbox verwijderd"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Bericht verstuurd"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "%s Berichten verplaatsen"
-msgstr[1] "%s Berichten verplaatsen"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Waarschuwing"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Annuleren"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr "Interne fout"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Geen bericht meer om te weergeven"
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Zoeken"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Zoeken..."
diff --git a/modoboa/locale/pt_BR/LC_MESSAGES/django.po b/modoboa/locale/pt_BR/LC_MESSAGES/django.po
index 9a2743a48..92009e34f 100644
--- a/modoboa/locale/pt_BR/LC_MESSAGES/django.po
+++ b/modoboa/locale/pt_BR/LC_MESSAGES/django.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# csmk, 2014
# Paulino Michelazzo , 2014
@@ -10,3092 +10,548 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2014-12-13 09:10+0000\n"
"Last-Translator: Paulino Michelazzo \n"
-"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/modoboa/language/pt_BR/)\n"
+"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
+"modoboa/language/pt_BR/)\n"
+"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Geral"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr "Nova versão do Modoboa disponível"
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autenticação"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Tipo de autenticação"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Local"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "O backend usado para autenticação"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Esquema padrão de senha"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (fraca)"
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (fraca)"
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (fraca)"
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (fraca)"
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (fraca)"
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Esquema usado para criptografar as senhas das caixas de correio"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr "Voltas"
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
-msgstr "Número de voltas a serem usadas (somnete usadas por sha256crypt e sha512crypt). Deve estar entre 1000 e 999999999, inclusive."
-
-#: core/app_settings.py:75
+msgstr ""
+"Número de voltas a serem usadas (somnete usadas por sha256crypt e "
+"sha512crypt). Deve estar entre 1000 e 999999999, inclusive."
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Chave secreta"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Chave utilizada para encriptar/decriptar senhas"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Configurações do LDAP"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Endereço do servidor"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "O endereço IP do nome DNS do servidor LDAP"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Porta do servidor"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "O número da porta TCP usada pelo servidor LDAP"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Usar conexão segura"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Usar uma conexão SSL/TLS para acessar o servidor LDAP"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Método de autenticação"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Pesquisar e vincular"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Vinculação direta"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Escolha o método de autenticação para usar"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Vincular DN"
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
-msgstr "O nome distinguível para usar quando vincular ao servidor LDAP. Deixe vazio para vincular anonimamente"
-
-#: core/app_settings.py:127
+msgstr ""
+"O nome distinguível para usar quando vincular ao servidor LDAP. Deixe vazio "
+"para vincular anonimamente"
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Vincular senha"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr "A senha usada quando vincular ao servidor LDAP (com 'Vincular DN')"
-
-#: core/app_settings.py:139
+#: core/app_settings.py:134
msgid "Users search base"
msgstr "Base de pesquisa de usuários"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "O nome distinto da base de pesquisa usada para encontrar usuários"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtro de pesquisa"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
-msgstr "Uma string opcional de filtro (por ex: '(objectClass=person)'). Para ser válida, deve estar entre parênteses."
-
-#: core/app_settings.py:160
+msgstr ""
+"Uma string opcional de filtro (por ex: '(objectClass=person)'). Para ser "
+"válida, deve estar entre parênteses."
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Usar template DN"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
"placeholder (ie. %(user)s)"
-msgstr "A template usada para construir um DN de usuário. Deve conter um placeholder (por ex: %(user)s)"
-
-#: core/app_settings.py:171
+msgstr ""
+"A template usada para construir um DN de usuário. Deve conter um placeholder "
+"(por ex: %(user)s)"
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Atributo de senha"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "O atributo usado para armazenar senhas de usuários"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Informe se o servidor LDAP é um Active Directory"
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Grupos de administradores"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
-"Members of those LDAP Posix groups will be created as domain administrators."
-" Use ';' characters to separate groups."
-msgstr "Membros dos grupos do LDAP Posix serão criados como administradores de domínio. Use o caractere ';' para separar grupos."
-
-#: core/app_settings.py:195
+"Members of those LDAP Posix groups will be created as domain administrators. "
+"Use ';' characters to separate groups."
+msgstr ""
+"Membros dos grupos do LDAP Posix serão criados como administradores de "
+"domínio. Use o caractere ';' para separar grupos."
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Base de pesquisa de grupos"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "O nome distinto da base de pesquisa usada para encontrar grupos"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Miscelânea"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Intervalo de verificação de verificações de topo"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Intervalo entre duas notificações de verificações de topo"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Verificar novas versões"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Verificar automaticamente se uma nova versão está disponível"
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Idade máxima do registro de log"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "A idade máxima em dias de um registro de log"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Itens por página"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Número de itens exibidos por página"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Redirecionamento de topo padrão"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
-msgstr "O redirecionamento padrão usado quando nenhuma aplicação é especificada"
-
-#: core/app_settings.py:268
+msgstr ""
+"O redirecionamento padrão usado quando nenhuma aplicação é especificada"
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "A chave deve ter 16, 24 ou 32 bytes de tamanho"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Sintaxe inválida"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Número de voltas inválido"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Este campo é obrigatório"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Mostrar"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Idioma preferido"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Idioma preferido para exibir páginas"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Nome de usuário"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Senha"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Senha antiga"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Nova senha"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Confirmação"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Senha antiga não confere"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Senhas não conferem"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr "senha"
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr "último login"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Você não pode deletar sua própria conta"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Falha ao atualizar senha: módulo LDAP não instalado"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "conta"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Linha inválida"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "Você não pode importar uma conta com um papel maior que o seu"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "O usuário simples '%s' deve ter um endereço de e-mail válido"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "os campos nome de usuário e e-mail não diferem de '%s'"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "ativado"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Marque para habilitar essa extensão"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "adicionado"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "modificado"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s pelo(s) usuário(s) %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "apagado"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Extensões"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Escolha a(s) extensão(ões) para usar"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Nome"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Versão"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Descrição"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Salvar"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Informação"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informações diversas sobre Modoboa"
-
#: core/templates/core/information.html:5
msgid "An update is available!"
msgstr "Uma atualização está disponível!"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
"\n"
-" Modoboa %(version)s is available for download. The list of all changes is available here .\n"
+" Modoboa %(version)s is available for download. The list "
+"of all changes is available here .\n"
+" "
+msgstr ""
+"\n"
+" O Modoboa %(version)s está disponível para download. A "
+"lista de todas as alterações está disponível aqui .\n"
" "
-msgstr "\n O Modoboa %(version)s está disponível para download. A lista de todas as alterações está disponível aqui .\n "
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "atualmente em uso."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Usuários ativos"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Nome do grupo"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Último login"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Logs"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Previamente no Modoboa..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Data"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Nível"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Mensagem"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Parâmetros"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configurar o Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Salvar"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Configurações do Modoboa"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Configurações"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Preferências"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Customizar Modoboa"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Perfil"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Atualizar sua informação pessoal"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Atualizar"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Sair"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Parêmetros salvos"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Modificações aplicadas."
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Usuário '%s' autenticado com successo"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "Seu usuário e senha não conferem. Por favor tente novamente."
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "O usuário '%s' saiu"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Perfil atualizado"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Preferências salvas"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Testar mensagens"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Enviar vírus"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Envia spam"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Mensagem enviada"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
"Welcome to the online demo! \n"
"Warning: the demo's concent is resetted every two hours.
\n"
-"To try the demo, the following users are available (username/password ):
\n"
+"To try the demo, the following users are available (username/password"
+"i>):
\n"
"\n"
" A super administrator : admin/password \n"
" A domain administrator : admin@demo.local/admin \n"
" A simple user : user@demo.local/user \n"
" \n"
"Please report any issue or give any suggestion to \n"
-" the mailing list .
\n"
-msgstr "\nBem-vindo a demonstração online \nAviso: consentimento da demonstração é reajustado a cada duas horas.
\nPara experimentar a demonstração, os seguintes usuários estão disponíveis (nome de usuário/senha ):
\n\nUm super administrador : admin/password \nUm administrador de domínio : admin@demo.local/admin \nUm usuário simples : user@demo.local/user \n \nPor favor, reporte qualquer problema ou faça alguma sugestão \nna lista de discussão .
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Console de administração"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Console baseado em web para gerenciar domínios, contas e aliases"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr "Administração"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Domínios"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Identidades"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Encaminhar"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Falha ao importar a conta (%s): domínio não existe"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "A caixa %s já existe"
-
-#: extensions/admin/__init__.py:186
-#, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Falha na importação de conta (%s): valor de quota errado"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr "alias de domínio"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Caixas de correios"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Tratar caixas de mensagens no sistema de arquivos."
-
-#: extensions/admin/app_settings.py:19
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr "Renomeia ou remove caixas de mensagens do sistema de arquivos quando elas são renomeadas ou removidas dentro do Modoboa"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Proprietário de caixas de mensagens"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "A conta UNIX que possui caixas de mensagens no sistema de arquivos"
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr "Quota padrão do domínio"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr "Quota padrão (em MB) aplicada para novos domínios sem nenhum valor especificado. Um valor de 0 indica que não existe quota."
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Remoção automática da conta"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr "Quando uma caixa de correio é removida, também remove a conta associada"
-
-#: extensions/admin/app_settings.py:49
-msgid "Automatic domain/mailbox creation"
-msgstr "Criação automática de domínio/caixa de correio"
-
-#: extensions/admin/app_settings.py:52
-msgid ""
-"Create a domain and a mailbox when an account is automatically created."
-msgstr "Criar um domínio e uma caixa de correio quando uma conta é automaticamente criada."
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr "Deve ser um inteiro positivo"
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr "Um caixa de mensagens é obrigatória"
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr "O nome de usuário. Deve ser um endereço de e-mail válido para usuários simples ou administradores com uma caixa de mensagens."
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Papel"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Escolher"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Qual nível de permissão terá esse usuário"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Para verificação, digite a mesma senha que a anterior."
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Ativado"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Os dois campos de senha não coincidiram."
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "Você não pode desabilitar seu própria conta"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "E-mail"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Cota"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr "Quota em MB para esta caixa de mensagens. Defina um valor customizado ou use o padrão do domínio. Deixe em branco para definir um valor ilimitado (não permitido para administradores de domínios)."
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Alias(es)"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr "Alias(es) para essa caixa de correio. Indique apenas um endereço por entrada, pressione ENTER para adicionar uma nova entrada. Use o caractere '*' para criar um alias 'pega-todos' (ex: *@exemplo.com)."
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "Domínio não existe"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Domínio(s)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Domínio(s) que o usuário administra"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Correio"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Permissões"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Conta atualizada"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Nova conta"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Conta criada"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "Endereço de e-mail"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr "A lista de endereços de distribuição. Use o caractere '*' para criar um endereço 'pega-todos' (ex: *@exemplo.com)."
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Destinatários"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr "Caixa(s) de correio(s) esse alias irá direcionar. Indique apenas um endereço por entrada, pressione ENTER para adicionar uma nova entrada."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "Você não tem acesso a esse domínio"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Caixa de entrada inválida"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Destinatário local %s não encontrado"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "Destinatário %s já existe"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Nenhum destinatário definido"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr "Quota padrão em MB aplicada para caixas de mensagens. Deixe em branco para usar o valor padrão."
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr "Alias(es) para esse domínio. Indique apenas um nome por entrada, pressione ENTER para adicionar uma nova entrada."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr "Já existe um %s com este nome"
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr "domínio"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Criar um administrador de domínio"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Criar automaticamente um administrador para este domínio"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr "O nome de administrador. Não inclua aqui o nome de domínio. Ele será automaticamente adicionado."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Criar alias"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Criar automaticamente aliases padrão para este domínio"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Formato inválido"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "O usuário '%s' já existe"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Domínio alterado"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Opções"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Novo domínio"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Domínio criado"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Nome do arquivo"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Separador"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Destinatário(s)"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Indique um ou mais destinatários separados por uma ','"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Manter cópias locais"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr "Encaminhar mensagens e armazenar cópias em sua caixa de correio local"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr "Você não pode definir um encaminhamento para um local de destino. Por favor, ao invés peça ao seu administrador para criar um alias."
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Selecione um arquivo"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Continuar em caso de erro"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Não tratar como erro objetos duplicados"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Criptografar senhas"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr "Marcar essa opção se as senhas contidas no seu arquivo estão criptografadas"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "endereço"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just"
-" enter an * character."
-msgstr "O endereço de alias (sem a parte do domínio). Para pegar qualquer endereço, basta digitar um caractere *."
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "Caixas de correio"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "Esse alias aponta para as caixas de correio"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Os aliases deste alias apontam para"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Verificar para ativar o alias"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "lista de distribuição"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "encaminhar"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Linha inválida: %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "O domínio '%s' não existe"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "nome"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "Nome do domínio"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Marque para ativar esse domínio"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr "Domínio"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr "Valor de quota inválido para o domínio '%s'"
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "Nome de alias"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "alvo"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "Esse alias aponta para o domínio"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Domínio desconhecido %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Endereço da caixa de correio (sem a parte @meu.dominio)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Falha ao recuperar a localização da caixa de mensagens (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "A quota é maior que o permitido pelo limite do domínio (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "Uma cota é requerida"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-msgid "Domain is disabled"
-msgstr "Domínio está desabilitado"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "MB"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr "Você não pode criar um novo administrador de domínio"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Estatísticas"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-msgid "Domains and identities"
-msgstr "Domínios e identidades"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr "Contadores globais"
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr "Tipo"
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-msgid "Quantity"
-msgstr "Quantidade"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Alias de domínios"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr "Contadores por domínios"
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Tags"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Ações"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-msgid "disabled"
-msgstr "desabilitado"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Administradores"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "Nenhum administrador de domínio definido"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Data de criação"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Data da última modificação"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Alias de caixas de correio"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Encaminhar e-mails automaticamente para outro endereço"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Nome completo/Destinatário"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Ajuda"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Importando..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Escolher um valor"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Usar valor padrão do domínio"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Endereço"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Valor"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Limite"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Uso (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Busca"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "Ativado"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "Ativada"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-msgid "List domains"
-msgstr "Listardomínios"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Adicionar domínio"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Importar"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Exportar"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Listar identidades"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Listar quotas"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Adicionar conta"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Adicionar alias"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Adicionar encaminhamento"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Adicionar lista de distribuição"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Ver as identidades de domínios"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "Remover %s?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Remover essa persmissão"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Um alias para esse nome já existe"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Criar"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Nova lista de distribuição"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Lista de distribuição criada"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Novo alias"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias criado"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Novo encaminhamento"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Encaminhamento criado"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Lista de distribuição modificada"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Encaminhamento modificado"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Alias modificado"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "Você não pode deletar seu próprio domínio"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Domínio deletado"
-msgstr[1] "Domínios deletados"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Exportar identidades"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Exportar domínios"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Solicitação inválida"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Conta deletada"
-msgstr[1] "Contas deletadas"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
+" the "
+"mailing list .\n"
+msgstr ""
+"\n"
+"Bem-vindo a demonstração online \n"
+"Aviso: consentimento da demonstração é reajustado a cada duas "
+"horas.
\n"
+"Para experimentar a demonstração, os seguintes usuários estão disponíveis "
+"(nome de usuário/senha ):
\n"
"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
+"Um super administrador : admin/password \n"
+"Um administrador de domínio : admin@demo.local/admin \n"
+"Um usuário simples : user@demo.local/user \n"
" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr "Forneça um arquivo CSV onde as linhas respeitam um dos seguintes formatos:\n\n domain; name; quota; enabled \n domainalias; name; targeted domain; enabled \n %s\n \nO primeiro elemento de cada linha é mandatório e deve ser igual a um dos valores indicados.
\nVocê pode usar um caractere diferente como separador.
\n"
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Importar domínios"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "O objeto já existe: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d objetos importados com sucesso"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr "Forneça um arquivo CSV onde as linhas respeitam um dos seguintes formatos:\n\naccount; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...] \nalias; address; enabled; internal recipient \nforward; address; enabled; external recipient \ndlist; address; enabled; recipient; recipient; ... \n \nO primeiro elemento de cada linha é mandatório e deve ser igual a um dos valores indicados.
\n\nVocê pode usar um caractere diferente como separador.
\n"
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Importar identidades"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Encaminhamento atualizado"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Frontend simples de gestão amavis"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Quarentena"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Configurações de quarentena"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Idade máxima da mensagem"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr "Tempo máximo (em dias) das mensagens em quarentena após exclusão"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Liberação de mensagens"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Remover mensagens seguradas"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr "Remover as mensagens marcadas como liberadas enquanto a limpa o banco de dados"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Modo de conexão com Amavis"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Modo usado para acessar o servidor PDP"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "Endereço do servidor PDP"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "Endereço do servidor PDP (modo inet)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "Porta do servidor PDP"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "porta do servidor PDP (modo inet)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "Socket do servidor PDP"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Caminho para o socket do servidor PDP (modo UNIX)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Permitir liberação direta de mensages"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Permitir que os usuários liberem as próprias mensagens"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Habilitar modo de auto-serviço"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Ativar o modo 'self-service'"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Notificações de remententes"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "O endereço de e-mail usado para enviar notificações"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr "Aprendizado manual"
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr "Habilitar aprendizado manual"
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr "Permitir que super administradores treinem o Spamassassin manualmente"
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr "O Spamassassin é local?"
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr "Dizer se o Spamassassin está rodando no mesmo servidor que o Modoboa"
-
-#: extensions/amavis/app_settings.py:99
-msgid "Default user"
-msgstr "Usuário padrão"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr "Nome do usuário proprietário do banco de dados bayesiano padrão"
-
-#: extensions/amavis/app_settings.py:107
-msgid "Spamd address"
-msgstr "Endereço Smapd"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr "O endereço IP onde o spamd pode ser acessado"
-
-#: extensions/amavis/app_settings.py:113
-msgid "Spamd port"
-msgstr "Porta Smapd"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr "A porta TCP onde o spamd está escutando"
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr "Habilitar aprendizado manual por domínio"
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr "Permite que administradores de domínio treinem o Spamassassin (dentro de bancos de dados dedicados por domínio)"
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr "Habilitar aprendizado manual por usuário"
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr "Permite que usuários simples treinem o Spamassassin (dentro de um banco de dados dedicado)"
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Número de e-mails exibidos por página"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Defina o número máximo de mensagens mostradas numa página"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr "Banco de Dados global"
-
-#: extensions/amavis/forms.py:94
-msgid "Domain's database"
-msgstr "Banco de dados de domínio"
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr "Usuário do banco de dados"
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr "Pedidos pendentes"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Filtro de conteúdo"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "Conexão ao amavis falhou: %s"
-
-#: extensions/amavis/lib.py:131
-msgid "No recipient found"
-msgstr "Nenhum destinatário encontrado"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Filtro de vírus"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "sim"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "não"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "padrão"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr "Ignorar ou não a checagem de vírus. Escolha 'padrão' para usar as configurações globais."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Filtro de spam"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr "Ignorar ou não a checagem de spam. Escolha 'padrão' para usar as configurações globais."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Filtro de banimento"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr "Ignorar ou não a checagem de banimentos. Escolha 'padrão' para usar as configurações globais."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Marcador de spam"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global"
-" settings."
-msgstr "Modificar o assunto do spam com texto específico. Escolha 'padrão' para usar as configurações globais."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Quarentena vazia"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Mensagem deletada"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d mensagem deletada com sucesso"
-msgstr[1] "%(count)d mensagens deletadas com sucesso"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Pedido enviado"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Mensagem liberada"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d pedido enviado"
-msgstr[1] "%(count)d pedidos enviados"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d mensagem liberada com sucesso"
-msgstr[1] "%(count)d mensagens liberadas com sucesso"
-
-#: extensions/amavis/views.py:360
-#, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d mensagem processada com sucesso"
-msgstr[1] "%(count)d mensagens processadas com sucesso"
-
-#: extensions/amavis/views.py:394
-msgid "Select a database"
-msgstr "Selecione um banco de dados"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr "Validar"
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Aguardando pedidos de liberação"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Limiares"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "ou mais é spam"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "ou mais descarta a mensagem de spam"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr "Pontuação"
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "Para"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "De"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Assunto"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-msgid "Released"
-msgstr "Liberado"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-msgid "Marked as spam"
-msgstr "Marcado como spam"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-msgid "Marked as non-spam"
-msgstr "Marcado como não-spam"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Gerenciamento de quarentena"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr "Selecionar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr "Limpar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Vírus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr "Bad Header"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Mal MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr "Banido"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Liberar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Deletar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-msgid "Mark as spam"
-msgstr "Marcar como spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr "Não marcar como spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Todas mensagens"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr "Tudo"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr "Somente limpar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr "Somente spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr "Somente Vírus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr "Somente Bad Header"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr "Somente Bad MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr "Somente banido"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] "\n%(counter)s solicitação de liberação está pendente para a ação.\n"
-msgstr[1] "\n%(counter)s solicitações de liberação estão pendentes para a ação.\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Esboço:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "De:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "Para:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Data:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Assunto:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Ato para essa mensagem:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Por favor, visite %(listingurl)s para a listagem completa."
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Voltar"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Exibir cabeçalhos completos"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr "Por recursos de administrador para limitar o número de objetos que eles podem criar"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Limites"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Limites padrão"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Administradores de domínio"
-
-#: extensions/limits/app_settings.py:15
-msgid ""
-"Maximum number of allowed domain administrators for a new administrator"
-msgstr "Número máximo de administradores de domínio permitidos para um novo administrador"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Número máximo de domínios permitidos para um novo administrador"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr "Número máximo de aliases de domínio permitidos para um novo administrador"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Número máximo de caixas de correio permitidas para um novo administrador"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Número máximo de aliases permitidos para um novo administrador"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Limite inválido"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Seus recursos ainda não foram inicializados"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "Você não tem permissão para definir valores ilimitados"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Revendedor"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Recursos"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s: limite alcançado"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Sem recursos suficientes"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr "Número máximo de administradores de domínios esse usuário pode criar"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Número máximo de domínio esse usuário pode criar"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Número máximo de aliases de domínio esse usuário pode criar"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Número máximo de caixas de correios esse usuário pode criar"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr "Número máximo de aliases de caixas de correio esse usuário pode criar"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "indefinido"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "ilimitado"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Uso de recursos"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Funcionalidade de auto resposta (modo férias) utilizando Postfix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Respostas automáticas"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Tempo de resposta automática"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr "Timeout em segundos entre duas respostas automáticas para o mesmo destinatário"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr "Assunto padrão"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr "Estou fora"
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr "Assunto padrão usado quando uma mensagem de auto-resposta é criada automaticamente"
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr "Conteúdo padrão"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr "Eu estou atualmente fora e responderei assim que retornar.\n\nSaudações,\n%(name)s\n"
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr "Conteúdo padrão usado quando uma mensagem de auto-resposta é criada automaticamente. A macro '%(name)s' será trocada pelo nome completo do usuário."
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr "Ativar sua resposta automática desta data"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Até"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Ativar auto resposta até essa data"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Esta data já passou"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr "Deve ser maior que a data de início"
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Mensagem de auto resposta"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr "Habilitar resposta automática"
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr "Habilitar ou desabilitar resposta automática do Postfix"
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "assunto"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "O assunto que aparecerá nos e-mails enviados"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "conteúdo"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "O conteúdo que parecerá nos e-mails enviados"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Ativar/Desativar sua resposta automática"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Resposta automática atualizada com sucesso."
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr "Defina uma mensagem para enviar automaticamente quando você estiver ausente"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr "Domínios de relay suportados pelo Postfix"
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr "Domínios de relay"
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr "Caminho do master.cf do Postfix"
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr "Caminho para o arquivo de configuração master.cf"
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr "Alias(es) para esse domínio de relay. Informe apenas um nome por entrada e pressione ENTER para adicionar uma nova entrada."
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr "alias de domínio de relay"
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr "domínio de relay"
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr "Domínio de relay modificado"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr "Adicionar um domínio de relay"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr "Número máximo de domínios de relay que este usuário pode criar"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr "Aliases de domínios de relay"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr "Número máximo de aliases de domínios de relay que este usuário pode criar"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr "\nrelaydomain; name; target host; service; enabled; verify recipients \nrelaydomainalias; name; target; enabled \n"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr "Número máximo permitido de domínios de relay para um novo administrador"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr "Número máximo permitido para aliases de domínios de relay para um novo administrador"
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr "O nome do serviço"
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr "host de destino"
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr "Destino remoto para este domínio"
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr "verificar destinatários"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr "Verificar destinatários válidos"
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr "Domínio de Relay"
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr "O alias do domínio de relay aponta para"
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr "O domínio de relay %s não existe"
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr "Domínio de relay criado"
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr "Novo domínio de relay"
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr "Domínio de relay removido"
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr "Scan"
-
-#: extensions/radicale/__init__.py:34
-msgid "Radicale management"
-msgstr "Gerenciamento do Radicale"
-
-#: extensions/radicale/__init__.py:38
-msgid ""
-"Management frontend for Radicale, a simple calendar and contact server."
-msgstr "Gerenciador de frontend para Radicale, um servidor simples de calendário e contato."
-
-#: extensions/radicale/app_settings.py:11
-msgid "Server settings"
-msgstr "Configurações do servidor"
-
-#: extensions/radicale/app_settings.py:15
-msgid "Server URL"
-msgstr "URL do Servidor"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr "A URL de seu servidor Radicale. Ela será usada para construir URL's de calendários."
-
-#: extensions/radicale/app_settings.py:24
-msgid "Rights management"
-msgstr "Gerenciamento de direitos"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr "Caminho do arquivo de direitos"
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr "Caminho para o arquivo que contém as definições de direitos"
-
-#: extensions/radicale/app_settings.py:36
-msgid "Allow calendars administration"
-msgstr "Permitir administração de calendários"
-
-#: extensions/radicale/app_settings.py:39
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr "Permite a administradores de domínio gerenciar calendários de usuários (leitura e escrita)"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr "Ler"
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr "Escrever"
-
-#: extensions/radicale/forms.py:134
-#, python-format
-msgid "Mailbox %s does not exist"
-msgstr "A caixa de correio '%s não existe"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr "Permissões"
-
-#: extensions/radicale/forms.py:162
-msgid "New calendar"
-msgstr "Novo calendário"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-msgid "Calendar created"
-msgstr "Calendário criado"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-msgid "Calendar updated"
-msgstr "Calendário atualizado"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr "Calendários"
-
-#: extensions/radicale/models.py:94
-msgid "User"
-msgstr "Usuário"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr "Compartilhado"
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-msgid "Calendar removed"
-msgstr "Calendário removido"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr "Novo calendário compartilhado"
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr "Enviar"
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr "Para acessar este calendário, use o seguinte endereço:"
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr "Proprietário"
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-msgid "Add calendar"
-msgstr "Adicionar calendário"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr "Adicionar calendário compartilhado"
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr "Ver detalhes do calendário"
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr "Editar %s"
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Plugin para criar facilmente filtros 'server-side'"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "Filters do Sieve"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Filtros de mensagem"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "Configurações do ManageSieve"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Endereço do servidor MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "Porta de escuta do servidor MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Conectar usando STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Usar a extensão STARTTLS "
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Mecanismo de autenticação"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Mecanismo de autenticação preferencial"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Modo editor"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Selecione o modo que você deseja que o editor trabalhe"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Marque para ativar esse conjunto de filtros"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Todas as seguintes"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Uma das seguintes"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "contém"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "não contém"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "é"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "não é"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Remetente"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Destinatário"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Cc"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Tamanho"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "é maior que"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "é menor que"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Mover mensagem para"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Redirecionar mensagem para"
-
-#: extensions/sievefilters/forms.py:110
-msgid "Wrong filter name"
-msgstr "Nome errado de arquivo"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr "Conexão com o servidor MANAGESIEVE falhou, verifique sua configuração"
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Sem espaço no servidor "
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Falha ao recuperar conjunto de filtros"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Novo filtro"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filtro criado"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Editar filtro"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filtro modificado"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filtro removido"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Falha ao remover filtro"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Conjunto de filtros salvo"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Conjunto de filtros criado"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Criar um novo conjunto de filtros"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Conjunto de filtros deletados"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Conjuntos de filtros ativados"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Condições"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Ativo"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Nenhum filtro definido ainda"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Conjuntos de filtro"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "ativo"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr "Nenhum conjunto de filtros definido ainda. Você deve criar um para poder definir filtros."
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Novo conjunto de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Salvar conjunto de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Ativar conjunto de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Remover conjunto de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Baixar"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Remover esse filtro"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Mover esse filtro para cima"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Mover esse filtro para baixo"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Estatísticas gráficas sobre o tráfego de e-mails usando RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Estatísticas gráficas"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Caminho para o arquivo de log"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Caminho para o arquivo de log usado para coletar estatísticas"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Diretório para armazenar arquivos RRD"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Caminho para o diretório onde os arquivos RRD são armazenados"
-
-#: extensions/stats/graphics.py:98
-msgid "Average traffic (msgs/min)"
-msgstr "Tráfego médio (msgs/min)"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "mensagens enviadas"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "mensagens recebidas"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "mensagens devolvidas"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "mensagens rejeitadas"
-
-#: extensions/stats/graphics.py:112
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Tamanho médio de tráfego (bytes/min)"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "tamanho recebido"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "tamanho enviado"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Tráfego de e-mail"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Não há estatísticas disponíveis"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Dia"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Semana"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Mês"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Ano"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr "Customizado"
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Conjunto gráfico desconhecido"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Período customizado inválido"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Buscar um domínio"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Aplicar"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Webmail IMAP simples"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Tamanho máximo de anexo"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Tamanho máximo de anexo em bytes (ou KB, MB, GB, se especificado)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "Configurações IMAP"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Endereço do seu servidor IMAP"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Usar uma conexão segura para acessar o servidor IMAP"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Porta de escuta do seu servidor IMAP"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "Configurações SMTP"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Endereço do seu servidor SMTP"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Modo de conexão segura"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Nenhuma"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Usar uma conexão segura para acessar o servidor SMTP"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Porta de escuta do seu servidor SMTP"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Autenticação obrigatória"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "Servidor precisa de autenticação"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Modo de exibição padrão da mensagem"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "O modo padrão usado ao exibir uma mensagem"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Ativar exibição de links em HTML"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Ativar/Desativar exibição de links em HTML"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Definir o número máximo de mensagens exibidas por página"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Taxa de atualização de escuta"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Taxa de atualização automática da pasta (em segundos)"
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr "Largura do contêiner da caixa de correio"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr "A largura do contêiner da caixa de correio"
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Pasta para Itens Deletados"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Pasta que irão as mensagens deletadas"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Pasta para Itens Recebidos"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Pasta onde irão as cópias de mensagens enviadas"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Pasta para Rascunhos"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Pasta onde irão os rascunhos"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Compondo mensagens"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Editor padrão"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "O editor padrão para usar ao escrever uma mensagem"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Texto da assinatura"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Assinatura de e-mail definida pelo usuário"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr "O valor deve ser um inteiro positivo (> 0)"
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Resposta do servidor"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Ação desconhecida"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "Cci"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Webmail"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d mensagem apagada"
-msgstr[1] "%(count)d mensagens apagadas"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Caixa de correio vazia"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Caixa de correio criada"
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Criar uma nova caixa de correio"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Editar caixa de correio"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Caixa de correio atualizada"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Falha ao salvar anexo:"
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "Anexo muito grande (limite: %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Anexos"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Consulta inválida"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Falha ao remover anexo:"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Anexo desconhecido"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "escreveu:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Mensagem original"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Falha ao recuperar o delimitador de hierarquia"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "Falha ao conectar no servidor IMAP: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Anexar"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Carregando..."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Caixa de correio parente"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr "Compor"
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Responder"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Responder a todos"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Opções de exibição"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Ativar links"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Desativar links"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Enviar"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-msgid "Mark as read"
-msgstr "Marcar como lido"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-msgid "Mark as unread"
-msgstr "Marcar como não lido"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Esvaziar pasta"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Editar a caixa de correio selecionada"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Remover a caixa de correio selecionada"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Compactar pasta"
-
-#: lib/dbutils.py:36
+"Por favor, reporte qualquer problema ou faça alguma sugestão \n"
+"na lista "
+"de discussão .
\n"
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Mensagem enviada"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "A conexão com o banco de dados %s não está configurada"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Permissão negada: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Permissão negada"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr "Enviar"
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Solicitação inválida"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Digite um nome de domínio válido"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Sim"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "Não"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Falha ao atualizar senha: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Usuário simples"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super administrador"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Administrador de domínio"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Desculpe"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "A página solicitada não existe."
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Um erro interno ocorreu."
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Buscar..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Do endereço"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Assunto"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Ambos"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Erro:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Ajuda:"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Fechar"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Anterior"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Próximo"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Bem-vindo ao Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Lembrar-me"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Entrar"
diff --git a/modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po b/modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po
index ed09d3685..9b7ed77c4 100644
--- a/modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po
@@ -1,184 +1,41 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Paulino Michelazzo , 2014
msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2014-12-13 09:14+0000\n"
"Last-Translator: Paulino Michelazzo \n"
-"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/modoboa/language/pt_BR/)\n"
+"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
+"modoboa/language/pt_BR/)\n"
+"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Nenhuma entrada de log a mais para mostrar"
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr "Nenhum domínio a mais para mostrar"
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "Não remova o diretório de domínio"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Esta operação removerá TODOS os dados associados com este domínio."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr "Esta operação removerá todos os dados associados com este domínio, exceto contas."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Nenhum administrador de domínio definido"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr "Nenhuma identidade a mais para mostrar"
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Não remova o diretório de caixas de mensagens"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr "Nenhuma quota a mais para mostrar"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr "Nenhuma mensagem a mais para mostrar"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Liberar esta seleção?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Apagar esta seleção?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-msgid "Mark this selection as spam?"
-msgstr "Marcar esta seleção como spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-msgid "Mark this selection as non-spam?"
-msgstr "Marcar esta seleção como não-spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Liberar esta mensagem?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Apagar esta mensagem?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr "Marcar como spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr "Marcar como não-spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Exibir cabeçalhos completos"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Esconder cabeçalhos completos"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr "Serviços atualizados"
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr "Nenhum calendário a mais para mostrar"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Remover este filtro?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Salvar alterações?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Remover conjunto de filtros?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Ativar este conjunto de filtros?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "ativo"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Buscar um domínio"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr "Nenhuma mensagem a mais nesra caixa de correio"
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Remover a caixa de mensagens selecionada?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Caixa de mensagens removida"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Mensagem enviada"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "Movendo %s mensagem"
-msgstr[1] "Movendo %s mensagens"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Atenção"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Cancelar"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr "Erro interno"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Nenhuma entrada a mais para mostrar"
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Busca"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Buscar..."
diff --git a/modoboa/locale/pt_PT/LC_MESSAGES/django.po b/modoboa/locale/pt_PT/LC_MESSAGES/django.po
index a30588c58..9a5962132 100644
--- a/modoboa/locale/pt_PT/LC_MESSAGES/django.po
+++ b/modoboa/locale/pt_PT/LC_MESSAGES/django.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Damien Duponchelle , 2013
# lusitan , 2013
@@ -13,3092 +13,545 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2014-12-29 12:51+0000\n"
"Last-Translator: Mike C. \n"
-"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/modoboa/language/pt_PT/)\n"
+"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/"
+"modoboa/language/pt_PT/)\n"
+"Language: pt_PT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: pt_PT\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Geral"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr "Existem uma nova versão do Modoboa disponivel"
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autenticação"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Tipo de autenticação"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Local"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Backend usado para autenticação"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Esquema pré-definido para passwords"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (fraco)"
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (fraco)"
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (fraco)"
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (fraco)"
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (fraco)"
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Esquema usado para encriptar as passwords das caixas de correio"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr ""
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
-
-#: core/app_settings.py:75
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Chave secreta"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Chave usada para encriptar/desencriptar passwords"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Definições do serviço de directório"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Endereço do Servidor"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "O endereço IP do servidor de DNS do servidor LDAP"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Porta do Servidor"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr " A porta TCP usada pelo servidor LDAP"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Utilizar uma ligação segura"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Usar SSL/TLS na ligaçao de acesso ao servidor LDAP"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Método de autenticação"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Procurar e vincular (bind)"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "\"Direct bind\""
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Escolher o método de autenticação"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "\"Bind DN\""
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
-msgstr "O nome único usado para fazer o \"bind\" ao servidor LDAP. Deixar vario para \"bind\" anónimo"
-
-#: core/app_settings.py:127
+msgstr ""
+"O nome único usado para fazer o \"bind\" ao servidor LDAP. Deixar vario "
+"para \"bind\" anónimo"
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Password para bind"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
-msgstr "A password usada para fazer o \"bind\" ao servidor LDAP (com 'Bind DN')"
-
-#: core/app_settings.py:139
+msgstr ""
+"A password usada para fazer o \"bind\" ao servidor LDAP (com 'Bind DN')"
+#: core/app_settings.py:134
msgid "Users search base"
msgstr "Base para pesquisa de utilizadores"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "O nome único a usar para pesquisa de utilizadores"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtro de pesquisa"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
-msgstr "Um filtro opcional (ex: '(objetClass=person)'). Tem de estar entre parênteses para ser válido"
-
-#: core/app_settings.py:160
+msgstr ""
+"Um filtro opcional (ex: '(objetClass=person)'). Tem de estar entre "
+"parênteses para ser válido"
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Template DN de utilizador"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
"placeholder (ie. %(user)s)"
-msgstr "O template usado para construir o DN (nome único). Deve apenas conter um 'placeholder' (ex: %(user)s) "
-
-#: core/app_settings.py:171
+msgstr ""
+"O template usado para construir o DN (nome único). Deve apenas conter um "
+"'placeholder' (ex: %(user)s) "
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Atributo de palavra-passe"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "O atributo utilizado para armazenar palavras-passe"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Especificar se o servidor LDAP e um Active Directory"
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Grupos de Administrador"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
-"Members of those LDAP Posix groups will be created as domain administrators."
-" Use ';' characters to separate groups."
-msgstr "Os membros destes grupos \"LDAP Posix\" serão criados como administradores de domínio. Use ';' para separar os grupos."
-
-#: core/app_settings.py:195
+"Members of those LDAP Posix groups will be created as domain administrators. "
+"Use ';' characters to separate groups."
+msgstr ""
+"Os membros destes grupos \"LDAP Posix\" serão criados como administradores "
+"de domínio. Use ';' para separar os grupos."
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Base para pesquisa de Grupos"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "O nome único para a base de pesquisa, usado para encontrar grupos"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Vários"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Intervalo de tempo para verificar notificações (no topo)"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Intervalo de tempo de verificação entre duas notificações (no topo)"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Procurar novas versões"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Verifica automaticamente se existem novas versões"
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Idade máxima do registo no log"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "A idade maxima do registo de um log, em dias, e de"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Itens por página"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Número de itens apresentados por página"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Redirecionamento pré-definido"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
-msgstr "O redirecionamento padrão usado quando nenhuma aplicação se encontra especificada"
-
-#: core/app_settings.py:268
+msgstr ""
+"O redirecionamento padrão usado quando nenhuma aplicação se encontra "
+"especificada"
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "A chave deve ter tamanho de 16, 24, ou 32 bytes"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Sintax inválida"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Número de linhas inválido"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Este campo é obrigatório"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Exibir"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Idioma preferido"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Idioma preferido para exibir páginas"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Nome de Utilizador"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Password"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Password antiga"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Nova password"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Confirmação"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Incompatibilidade da password antiga"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Passwords não coincidem"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr "password"
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr "último login"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Não pode apagar a sua própria conta"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Falha ao actualizar password: Modulo LDAP não instalado"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "conta"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Linha inválida"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "Não é possível importa uma conta com permissões superiores"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "O simple utilizador '%s' deve ter endereço de e-mail válido"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
-msgstr "Os campos nome de utilizador e endereço de email não deve ser diferente para '%s'"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "ativo"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Marque para ativar esta extensão"
-
-#: core/models.py:511
+msgstr ""
+"Os campos nome de utilizador e endereço de email não deve ser diferente para "
+"'%s'"
+#: core/models.py:461
msgid "added"
msgstr "acrescentado"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "modificado"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s pelo utilizador %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "apagado"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Extras"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Escolher a(s) extensões a usar "
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Nome"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Versão"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Descrição"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Guardar"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Informação"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informações variadas sobre Modoboa"
-
#: core/templates/core/information.html:5
msgid "An update is available!"
msgstr "Uma nova versão está disponível!"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
"\n"
-" Modoboa %(version)s is available for download. The list of all changes is available here .\n"
+" Modoboa %(version)s is available for download. The list "
+"of all changes is available here .\n"
" "
msgstr ""
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "está de momento em uso."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Utilizadores ativos"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Nome do grupo"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Último login"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Logs"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Anteriormente no Modoboa..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Data"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Nível"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Mensagem"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Parâmetros"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configurar Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Guardar"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Definições do Modoboa"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Definições"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Preferências"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Personalizar Modoboa"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Perfil"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Atualizar o sua informação pessoal"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Actualizar"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Sair"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Parâmetros salvos"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Alterações efectuadas."
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "O utilizador '%s' fez login com sucesso"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "O seu nome de utilizador"
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "O utilizador '%s' fez logout"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Perfil atualizado"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Preferências salvas"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Mensagens de teste"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Enviar vírus"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Enviar spam"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Mensagem enviada"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
"Welcome to the online demo! \n"
"Warning: the demo's concent is resetted every two hours.
\n"
-"To try the demo, the following users are available (username/password ):
\n"
+"To try the demo, the following users are available (username/password"
+"i>):
\n"
"\n"
" A super administrator : admin/password \n"
" A domain administrator : admin@demo.local/admin \n"
" A simple user : user@demo.local/user \n"
" \n"
"Please report any issue or give any suggestion to \n"
-" the mailing list .
\n"
-msgstr "\nBem-vindo à demo online! \nAviso: os conteúdos desta demo são limpos a cada duas horas.
\nPara experimentar a demo, estão disponíveis os seguintes utilizadores (username/password ):
\n\n Super administrador: admin/password \n Administrador de domínio: admin@demo.local/admin \n Utilizador básico: user@demo.local/user \n \nPara reportar qualquer problema ou apresentar uma sugestão, utilize o seguinte link \n mailing list .
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Consola de Administração"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Consola baseada na web para gestão de domínios, contas e aliases"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr "Administração"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Domínios"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Identidades"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Reencaminhar"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Importação da conta falhou (%s): domínio não existe"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "Caixa de correio %s já existe"
-
-#: extensions/admin/__init__.py:186
-#, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Importação da conta falhou (%s): valor para quota inválido"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr "'Alias' de domínio"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Caixas de Correio"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Lidar com caixas de correio no sistema de ficheiros"
-
-#: extensions/admin/app_settings.py:19
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr "Renomear ou remover as caixas de correio no sistema de ficheiros quando estas são renomeadas no Modoboa"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Dono das caixas de correio"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "A conta UNIX que detém as caixas de correio no sistema de ficheiros"
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr "Quota pré-definida para o domínio"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr "Quota (em MB) a aplicar a domínios recentemente criados sem valor especificado. Um valor de 0 implica sem quota."
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Remoção automática de conta"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr "Ao remover uma caixa de correio estará também a remover a conta associada"
-
-#: extensions/admin/app_settings.py:49
-msgid "Automatic domain/mailbox creation"
-msgstr "Criação automatica de domino/caixa de correio"
-
-#: extensions/admin/app_settings.py:52
-msgid ""
-"Create a domain and a mailbox when an account is automatically created."
-msgstr "Criar um dominio e uma caixa de correio quando uma conta é criada automátiamente."
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr "Tem de ser um inteiro, positivo"
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr "É necessária uma caixa de correio"
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
+" the "
+"mailing list .\n"
msgstr ""
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Papel"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Escolher"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Que nível de permissões terá o utilizador"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Repita a password acima, para verificação."
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Ativo"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Os dois campos de password não são idênticos."
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "Não pode desativar a sua própria conta"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "E-mail"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Quota"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr "Quota em MB para esta caixa de correio. Definir uma valor personalizado ou usar o valor predefinido pelo domínio. Deixar em branco para definir uma valor ilimitado (não permitido para administradores do domínio)."
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Alias(es)"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr "Alias(es) desta caixa de correio. Indique apenas um endereço por entrada, clique ENTER para adicionar uma nova entrada. Use o '*' para criar um alias 'catchall' (ex: *@domain.tld)."
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "O domínio não existe"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Domínio(s)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Domínio(s) administrado pelo utilizador"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Correio"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Permissões"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Conta actualizada"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Nova conta"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Conta criada"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "Endereço de e-mail"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr "Os endereços da lista de distribuição. Use o '*' para criar um endereço 'catchall' (Ex: *@domain.tld)."
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Destinatários"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr "Caixa(s) de correio para o qual este 'alias' aponta. Indicar apenas um endereço por entrada, pressionar ENTER para acrescentar uma nova entrada."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "Não tem acesso a este domínio"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Caixa de correio inválida"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "O destinatário local %s não foi encontrado"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "O destinatário %s já existe"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Sem destinatário definido"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr "Quota (em MB) aplicada às caixas de correio. Deixe em branco para manter o valor pré-definido."
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr "Alias(es) deste domínio. Indicar apenas um nome por entrada, pressionar ENTER para acrescentar uma nova entrada."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr "Já existe um(a) %s com este nome. "
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr "domínio"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Criar um administrador de domínio"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Criar automaticamente um administrador para este domínio"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr "O nome do administrador. Não inclua o nome do domínio já que este será automaticamente anexado."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr " Criar aliases"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Criar automaticamente aliases para este domínio"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Formato inválido"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "O utilizador '%s' já existe"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Domínio alterado"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Opções"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Novo domínio"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Domínio criado"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Nome do ficheiro"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Separador"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Destinatário(s)"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Indicar um ou mais destinatários separados por ','"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Conservar cópias locais"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr "Reencaminhar mensagens e armazenar cópias na sua caixa de correio local"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr "Não é possível definir um reencaminhamento para um destino local. Por favor informe-se junto de um administrador para criar um alias."
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Escolha um ficheiro"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Continua com erro"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Não tratar objetos duplicados como erro"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Passwords encriptadas"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr "Marque esta opção se as senhas contidas no arquivo não são encriptadas"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "endereços"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just"
-" enter an * character."
-msgstr "O endereço do alias (sem a parte do domínio). Para um endereço 'cath-all', digite apenas o caractere *"
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "caixas de correio"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "As caixas de correio para onde este alias irá apontar"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Este 'aliases' aponta para"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Marcar para ativar este alias"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "lista de distribuição"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "reencaminhar"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Linha inválida: %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "O domínio '%s' não existe"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "nome"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "O nome do domínio"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Marcar para ativar este domínio"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr "Domínio"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr "Valor de quota inválido para o dominio '%s'"
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "O nome do 'alias'"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "alvo"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "O domínio para o qual este alias irá apontar"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Domínio desconhecido: %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Endereços das caixas de correio (sem a parte @domain.tld)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Falha ao recuperar a localização da caixa de correio (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "A quota excede o limite permitido pelo domínio (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "É necessário uma quota"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-msgid "Domain is disabled"
-msgstr "O dominio está inativo"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "MB"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr "Não pode criar administradores de domínio"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Estatísticas"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-msgid "Domains and identities"
-msgstr "Domínios e identidades"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr "Contadores globais"
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr "Tipo"
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-msgid "Quantity"
-msgstr "Quantidade"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Aliases de domínio"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr "Contadores por-domínio"
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Tags"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Ações"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-msgid "disabled"
-msgstr "inativo"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Administradores"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "Nenhum administrador de domínio definido"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Data de criação"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Data da última modificação"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Aliases para caixas de correio"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Reenviar automaticamente e-mails para outro endereço"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Nome Completo / Destinatário"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Ajuda"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "A importar..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Escolha um valor"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Usar um valor padrão de domínio"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Endereço"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Valor"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Limite"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Utilização (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Procurar"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "enabled_m"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "enabled_f"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-msgid "List domains"
-msgstr "Listar domínios"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Adicionar domínio"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Importar"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Exportar"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Listar identidades"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Listar as quotas"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Adicionar conta"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Adicionar 'alias'"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Adicionar reencaminhamento"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Adicionar lista de distribuição"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Visualizar as identidades do domínio"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "Eliminar %s?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Remover esta permissão"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Já existe um 'alias' com este nome"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Criar"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Nova lista de distribuição"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "A lista de distribuição foi criada"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Novo 'alias'"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias criado"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Novo reencaminhamento"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Reencaminhamento criado"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Lista de distribuição modificada"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Reencaminhamento modificado"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "'Alias' modificado"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "Não é possível eliminar o seu próprio domínio"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Domínio criado"
-msgstr[1] "Domínios eliminados"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Exportar identidades"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Exportar domínios"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Pedido inválido"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Conta eliminada"
-msgstr[1] "Contas eliminadas"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
+"\n"
+"Bem-vindo à demo online! \n"
+"Aviso: os conteúdos desta demo são limpos a cada duas horas.
\n"
+"Para experimentar a demo, estão disponíveis os seguintes utilizadores "
+"(username/password ):
\n"
"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
+" Super administrador: admin/password \n"
+" Administrador de domínio: admin@demo.local/admin \n"
+" Utilizador básico: user@demo.local/user \n"
" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Importar domínios"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "Este objeto já existe: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d objetos importados com sucesso"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Importar identidades"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Reencaminhamento atualizado"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Interface de gestão básica do amavis"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Quarentena"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Definições de quarentena"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Idade maxima da messagem"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr "Tempo máximo que as mensagens ficam na quarentena (em dias) até serem eliminadas"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Libertar mensagens"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Remover mensagens libertadas"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr "Remova as mensagens, marcadas como enviadas, durante a limpeza da base de dados"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Modo de ligação ao amavis"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Método usado para aceder ao servidor PDP"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "Endereço do servidor PDP"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "Endereço do servidor PDP (método inet)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "Porta do servidor PDP"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "Porta do servidor PDP (método inet)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "Socket do servidor PDP"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Caminho para a socket do servidor PDP (método unix)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Permitir envio direto"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Permitir que aos utilizadores libertar mensagens diretamente"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Ativar o modo de self-service"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Ativar o modo 'self-service'"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Notificações de remetente"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "O endereço de e-mail usado para enviar notificações"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr "Aprendizagem manual"
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr "Ativar a função de aprendizagem manual"
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr "Permitir aos super administradores treinar manualmente o spamassassin"
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr "O spamasassin está instalado localmente?"
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr "Indicar se o spamassassin está a correr no mesmo servidor que o modoboa"
-
-#: extensions/amavis/app_settings.py:99
-msgid "Default user"
-msgstr "Utiizador pré-definido"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr "Nome do utilizador que detém as permissões de dono da base de dados bayesian"
-
-#: extensions/amavis/app_settings.py:107
-msgid "Spamd address"
-msgstr "Endereço do Spamd"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr "Endereço de IP onde o spamd está a correr"
-
-#: extensions/amavis/app_settings.py:113
-msgid "Spamd port"
-msgstr "Porta do Spamd"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr "Porta TCP onde o Spmad está à escuta"
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr "Ativar a função de aprendizagem manual por domínio"
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr "Permitir aos super administradores treinar manualmente o spamassassin ( com bases de dados dedicadas por domínio)"
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr "Permitir aos utilizadores simples usar a aprendizagem manual"
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr "Permitir aos utilizadores simples treinar manualmente o spamassassin ( com bases de dados dedicadas)"
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Número de e-mails a visíveis por página"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Definir o número máximo de mensagens apresentadas por página"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr "Base de dados Global"
-
-#: extensions/amavis/forms.py:94
-msgid "Domain's database"
-msgstr "Base de dados do Domínio"
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr "Base de dados do Utilizador"
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr "Pedidos pendentes"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Filtro de conteúdo"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "Não foi possível estabelecer ligação com o amavis: %s"
-
-#: extensions/amavis/lib.py:131
-msgid "No recipient found"
-msgstr "Destinaário não encontrado"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Filtro de vírus"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "sim"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "não"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "predifinido"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr "Ignorar a verificação de vírus ou não. Escolher 'predefinido' para utilizar as definições gerais."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Filtro de spam"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr "Ignorar filtros de spam ou não. Escolher 'predefinido' para utilizar as definições gerais."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Ficheiros proibidos"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr "Ignorar a verificação de ficheiros proibidos. Escolher 'predefinido' para utilizar as definições gerais."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Marcador spam"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global"
-" settings."
-msgstr "Modifique o assunto de spam usando o texto especificado. Escolha 'default' para usar as configurações globais."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Quarentena vazia"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Mensagem apagada"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d mensagem eliminada com sucesso"
-msgstr[1] "%(count)d mensagens eliminadas com sucesso"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Pedido enviado"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Mensagem libertada"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d pedido enviado"
-msgstr[1] "%(count)d pedidos enviados"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d mensagem libertada com sucesso"
-msgstr[1] "%(count)d mensagens libertadas com sucesso"
-
-#: extensions/amavis/views.py:360
-#, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d mensagem processada com sucesso"
-msgstr[1] "%(count)d mensagens processadas com sucesso"
-
-#: extensions/amavis/views.py:394
-msgid "Select a database"
-msgstr "Selecionar base de dados"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr "Validar"
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Pedidos de laçamento pendentes"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Limites"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "ou mais, é spam"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "ou mais, excluir mensagem de spam"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr "Pontuação"
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "Para"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "De"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Assunto"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-msgid "Released"
-msgstr "Libertar"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-msgid "Marked as spam"
-msgstr "Marcado com spam"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-msgid "Marked as non-spam"
-msgstr "Marcado como \"não é spam\""
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Gestão de Quarentena"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr "Selecionar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr "Limpar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Vírus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr "Cabeçalho inválido"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Formato MIME inválido"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr "Banido"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Libertar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Eliminar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-msgid "Mark as spam"
-msgstr "Marcar como spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr "Marcar como \"não é spam\""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Todas as mensagens"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr "Tudo"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr "Apenas limpar"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr "Apenas Spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr "Apenas Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr "Apenas Cabeçalho Inválido"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr "Apenas conteúdo MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr "Apenas Banidos"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] "\n%(counter)s pedido de libertação pendente\n"
-msgstr[1] "\n%(counter)s pedidos de libertação pendentes\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Rascunho:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "De:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "Para:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Data:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Assunto:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Atuar nesta mensagem:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Por favor visitar %(listingurl)s para uma listagem completa."
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Voltar"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Ver todos os cabeçalhos"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr "Limite do número de objetos criados, por administrador"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Limites"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Limites predefinidos"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Administradores de domínio"
-
-#: extensions/limits/app_settings.py:15
-msgid ""
-"Maximum number of allowed domain administrators for a new administrator"
-msgstr "Número máximo permitido de administradores de domínio para um novo administrador"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Número máximo permitido de domínios para novo administrador"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr "Número máximo permitido de aliases de domínio para um novo administrador"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Número máximo permitido de caixas de correio para novo administrador"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Número máximo de aliases permitidas para um novo administrador"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Limite inválido"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Ainda não inicializou os seus conteúdos"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "Não está autorizado a definir valores ilimitados"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Revendedor"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Recursos"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s: limite atingido"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Recursos insuficientes"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr "Número máximo de administradores de domínio que este utilizador pode criar"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Número máximo de domínios que este utilizador pode criar"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Número máximo de aliases de domínio que este utilizador pode criar"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Número máximo de caixas de correio que este utilizador por criar"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr "Número máximo de aliases para caixas de correio que este utilizador por criar"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "indefinido"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "ilimitado"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Utilização de recursos"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Funcionalidade de resposta automática (férias) usando Postfix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Respostas automáticas"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Tempo limite de resposta automática"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr "Tempo limite em segundos entre duas respostas automáticas para o mesmo destinatário"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr "Assunto pré-definido"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr "Estou indisponível"
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr "Assunto pré-definido, usado nas respostas automáticas."
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr "Contéudo pré-definido"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr "Estou indisponível de momento. Responderei logo que possível.\n\nMelhores cumprimentos,\n%(name)s\n\n"
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr "Ative a resposta automática a partir desta data"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Até"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Ativar o seu aviso de ausência até esta data"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Esta data ultrapassa"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr "Tem de ser posterior à data de inicio."
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Mensagem de resposta automática"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr "Ativar resposta automática"
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr "Ativar ou Inativar a resposta automática do Postfix"
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "assunto"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "O assunto que irá constar nos e-mails enviados"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "conteúdo"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "O conteúdo que irá constar nos e-mails enviados"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Ativar/desativar repostas automáticas"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Mensagem de resposta automática actualizada com sucesso"
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr "Enviar a mensagem automaticamente quando estiver ausente"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr ""
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr ""
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr "Caminho para para o ficheiro master.cf Postfix"
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr "Caminho para o ficheiro de configuração master.cf"
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr ""
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr ""
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr "O nome do serviço"
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr "endereço de destino"
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr "Endereço de destino remoto deste domínio"
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr "verificar destinatários"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr "Analisar se os destinatáris são válidos"
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr ""
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr "Analisar"
-
-#: extensions/radicale/__init__.py:34
-msgid "Radicale management"
-msgstr "Gestão do Radicale"
-
-#: extensions/radicale/__init__.py:38
-msgid ""
-"Management frontend for Radicale, a simple calendar and contact server."
-msgstr "Front-end para gestão do Radicale, o servidor simples de contactos e calendário."
-
-#: extensions/radicale/app_settings.py:11
-msgid "Server settings"
-msgstr "Definições do Servidor"
-
-#: extensions/radicale/app_settings.py:15
-msgid "Server URL"
-msgstr "Endereço do Servidor"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr "O endereço do servidor Radicale. Será usado para construir os endereços dos Calendários."
-
-#: extensions/radicale/app_settings.py:24
-msgid "Rights management"
-msgstr "Gestão de Permissões"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr "Caminho para o ficheiro de permissões"
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr "Caminho para o ficheiro que contém as permissões de utilizadores"
-
-#: extensions/radicale/app_settings.py:36
-msgid "Allow calendars administration"
-msgstr "Permitir administração de calendários"
-
-#: extensions/radicale/app_settings.py:39
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr "Permitir aos administradores de domínio gerir calendários de utilizadores (leitura e escrita)"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr "Leitura"
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr "Escrita"
-
-#: extensions/radicale/forms.py:134
-#, python-format
-msgid "Mailbox %s does not exist"
-msgstr "Caixa de correio %s não existe"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr "Permissões"
-
-#: extensions/radicale/forms.py:162
-msgid "New calendar"
-msgstr "Novo calendário"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-msgid "Calendar created"
-msgstr "Calendário criado"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-msgid "Calendar updated"
-msgstr "Calendário atualizado"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr "Calendários"
-
-#: extensions/radicale/models.py:94
-msgid "User"
-msgstr "Utilizador"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr "Partilhado"
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-msgid "Calendar removed"
-msgstr "Calendário removido"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr "Novo calendário partilhado"
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr "Enviar"
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr "Para aceder a este calendário, use o seguinte endrerço:"
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr "Dono"
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-msgid "Add calendar"
-msgstr "Adicionar calendário"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr "Adicionar calendário partilhado"
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr "Ver detalhes do Calendario"
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr "Editar %s"
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Plugin para criar facilmente filtros 'server-side'"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "Filtros Sieve"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Gerir filtros"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "Definições do MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Endereço do servidor MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "Porta atribuída ao servidor MANAGESIEVE"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Ligar via STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Usar a extensão STARTLS"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Mecanismo de autenticação"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Método de autenticação preferencial"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Modo de edição"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Seleccione o modo de funcionamento do editor"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Marque para ativar estes filtros"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Todos estes"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Algum destes"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "contém"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "não contém"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "é"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "não é"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Remetente"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Destinatário"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Cc"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Tamanho"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "é maior do que"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "é menor do que"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Mover mensagens para"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Reencaminhar mensagens para"
-
-#: extensions/sievefilters/forms.py:110
-msgid "Wrong filter name"
-msgstr "Filtro inválido"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr "Ligação ao servidor MANAGESIEVE falhou, valide a configuração"
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Espaço insuficiente no servidor"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Falha ao recuperar os filtros definidos"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Novo filtro"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filtro criado"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Editar filtro"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filtro modificado"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filtro removido"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Falha ao remover filtro"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Grupo de filtros guardado"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Grupo de filtros criado"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Criar novo grupo de filtros"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Grupo de filtros eliminado"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Grupo de filtros ativado"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Condições"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Ativo"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Ainda não existe nenhum filtro definido"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Grupos de filtros"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "ativo"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr "Não existem grupos de filtros. Terá de criar um para poder definir filtros."
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Novo grupo de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Guardar grupo de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Ativar grupo de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Eliminar grupo de filtros"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Descarregar"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Eliminar este filtro"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Mover este filtro para cima"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Mover este filtro para baixo"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Estatísticas gráficas sobre tráfego de email usando RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Estatísticas gráficas"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Caminho para o ficheiro log"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Caminho para o ficheiro de log usado para recolher as estatísticas"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Diretório para armazenar os ficheiros RRD"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Caminho para o diretório onde os ficheiros RRD são guardados"
-
-#: extensions/stats/graphics.py:98
-msgid "Average traffic (msgs/min)"
-msgstr "Trafego em média (msgs/min)"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "mensagens enviadas"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "mensagens recebidas"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "mensagens devolvidas"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "mensagens rejeitadas"
-
-#: extensions/stats/graphics.py:112
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Tráfego em média normal por tamanho (bytes/min)"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "tamanho recebido"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "tamanho enviado"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Tráfego de correio"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Não há estatísticas disponíveis"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Dia"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Semana"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Mês"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Ano"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr "Personalizado"
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Conjunto de gráficos desconhecido"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Período personalizado inválido"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Procurar um domínio"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Aplicar"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Sistema de Webmail IMAP básico"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Tamanho máximo do anexo"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Tamanho máximo do anexo em bytes (ou KB, MB, GB se especificado)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "Definições IMAP"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Endereço do servidor IMAP"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Usar uma ligação segura para aceder ao servidor IMAP"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Porta do servidor IMAP"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "Definições SMTP"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Endereço do servidor IMAP"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Modo de ligação segura"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Nenhum"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Usar uma ligação segura para aceder ao servidor SMTP"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Porta do servidor SMTP"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Autenticação necessária"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "O servidor requer autenticação"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Modo de visualização predefinido"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "O modo de visualização de mensagem que será usado por defeito"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Ativar visualização de links HTML"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Ativar/desativar"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Define o número máximo de mensagens a mostrar por página"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Taxa de actualização da listagem"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Taxa de actualização automática de pastas (em segundos)"
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr "Largura do caixilho das caixas de correio"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr "Largura do caixilho da lista de caixa de correio"
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Pasta para Itens Eliminados"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Pasta para a qual os itens eliminados são enviados"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Pasta para Itens Enviados"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Pasta onde as copias das mensagens enviadas são guardadas"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Pasta para Rascunhos"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Pasta onde ficam guardados os rascunhos"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "A criar mensagem"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Editor predefinido"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "O editor a ser usado por defeito na composição de mensagens"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Assinatura"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Assinatura de email definida pelo utilizador"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr "O valor tem de ser um inteiro, positivo (> 0)"
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Resposta do servidor"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Acção desconhecida"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "Cci"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Webmail"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d mensagens eliminadas"
-msgstr[1] "%(count)d mensagens eliminadas"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Caixa de correio vazia"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Caixa de correio criada"
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Criar nova caixa de correio"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Editar caixa de correio"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Caixa de correio actualizada"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Falha ao salvar o anexo:"
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "Anexo demasiado grande (limite %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Anexos"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Pesquisa inválida"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Falha ao remover os anexos:"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Anexo desconhecido"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "escreveu:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Mensagem original"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Falha ao recuperar hierarquia delimitador"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "A ligação ao servidor IMAP falhou: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Anexar"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "A carregar..."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Caixa de correio principal"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr "Escrever"
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Responder"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Responder a todos"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Opções de Visualização"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Ativar links"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Desativar links"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Enviar"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-msgid "Mark as read"
-msgstr "Marcar como lida"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-msgid "Mark as unread"
-msgstr "Marcar como não lida"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Esvaziar pasta"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Editar caixa de correio selecionada"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Eliminar caixa de correio selecionada"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Comprimir pasta"
-
-#: lib/dbutils.py:36
+"Para reportar qualquer problema ou apresentar uma sugestão, utilize o "
+"seguinte link \n"
+" mailing "
+"list .
\n"
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Mensagem enviada"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "A ligação à base de dados %s não está devidamente configurada"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Acesso negado: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Acesso negado"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr "Enviar"
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Pedido inválido"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Introduzir um nome de domínio válido "
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Sim"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "Não"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Falha ao actualizar a password: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Utilizador simples"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super Administrador"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Administrador de domínio"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Lamentamos"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "A página solicitada não existe."
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Ocorreu um erro interno."
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Procurar..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Do endereço"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Assunto"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Ambos"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Erro:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Ajuda:"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Fechar"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Anterior"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Seguinte"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Benvindo ao Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Lembrar-me"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Entrar"
diff --git a/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po b/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po
index 666c4f47b..ecdac6a8b 100644
--- a/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# lusitan , 2013
# lusitan , 2013
@@ -13,177 +13,34 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2014-12-29 12:08+0000\n"
"Last-Translator: Mike C. \n"
-"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/modoboa/language/pt_PT/)\n"
+"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/"
+"modoboa/language/pt_PT/)\n"
+"Language: pt_PT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: pt_PT\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Não há mais entradas do registo para mostrar"
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr "Não existem mais dominios para mostrar"
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "Não excluir o diretório do domínio"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Esta operação irá remover TODOS os dados associados a este domínio."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr "Esta operação irá remover TODOS os dados associados a este domínio, excepto as contas."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Não está definido nenhum administrador para o domínio"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr "Não existem mais identidades para mostrar"
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Não excluir o diretório da caixa de correio"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr "Não existem mais quotas para mostrar"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr "Não existem mais mensagens para mostrar"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Libertar itens seleccionados?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Eliminar itens seleccionados?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-msgid "Mark this selection as spam?"
-msgstr "Marcar os items selecionados como spam"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-msgid "Mark this selection as non-spam?"
-msgstr "Marcar os items selecionados como \"não é spam\""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Libertar esta mensagem?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Eliminar esta mensagem?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr "Marcar como spam?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr "Marcar como \"não é spam\""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Ver cabeçalho completo"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Esconder cabeçalho completo"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr "Atualizados os serviços"
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr "Não existem mais calendários para mostrar"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Remover este filtro?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Guardar alterações?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Limpar filtros definidos?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Activar estes filtros?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "activo"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Pesquisar domínio"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr "Não existem mais mensagens nesta caixa de correio."
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Remover a caixa de correio seleccionada"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Caixa removida"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Mensagem enviada"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "A mover %s mensagem"
-msgstr[1] "A mover %s mensagens"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Aviso"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Cancelar"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr "Erro interno"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Não existem mais entradas a mostrar"
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Procurar"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Pesquisar..."
diff --git a/modoboa/locale/ru/LC_MESSAGES/django.po b/modoboa/locale/ru/LC_MESSAGES/django.po
index 341cc1c92..351909c34 100644
--- a/modoboa/locale/ru/LC_MESSAGES/django.po
+++ b/modoboa/locale/ru/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2013-12-03 09:35+0000\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: Russian (http://www.transifex.com/projects/p/modoboa/language/"
@@ -18,176 +18,128 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Основные"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr ""
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Аутентификация"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Тип аутентификации"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Локальный"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Базовая программа для проверки подлинности"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Схема пароля по умолчанию"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr ""
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr ""
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr ""
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr ""
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr ""
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Схема используемая для шифровании пароля почтового ящика."
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr ""
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
-
-#: core/app_settings.py:75
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Секретный ключ"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Ключ для шифрования паролей"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Параметры LDAP"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Адрес сервера"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "IP адрес или DNS имя сервера LDAP"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Порт сервера"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Номер TCP порта LDAP сервера"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Использовать безопасное соединение"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Использовать SSL/TLS соединение с LDAP сервером"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Метод аутентификации"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Найти и соединиться"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Прямое соединение"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Выберите метод аутентификации "
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Соединится с DN "
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
msgstr ""
"Отличительное имя используемое для соединения с LDAP сервером. Оставьте "
"пустым для анонимного соединения"
-
-#: core/app_settings.py:127
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Пароль для соединения"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr "Пароль для соединения с LDAP сервером"
-
-#: core/app_settings.py:139
+#: core/app_settings.py:134
msgid "Users search base"
msgstr ""
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr ""
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Фильтр поиска"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
msgstr ""
"Необязательная срока поиска (например '(objectClass=person)') Значение нужно "
"заключить в скобки"
-
-#: core/app_settings.py:160
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Шаблон пользователя DN"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
@@ -195,267 +147,180 @@ msgid ""
msgstr ""
"Шаблон используется для построения запросов к DN Он должен содержать атрибут "
"например (%(user)s)"
-
-#: core/app_settings.py:171
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Свойства пароля"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Свойства используемые для сохранения пользовательских паролей"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Укажите, если LDAP сервер в Active Directory"
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr ""
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
msgstr ""
-
-#: core/app_settings.py:195
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr ""
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr ""
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Прочее"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
#, fuzzy
msgid "Top notifications check interval"
msgstr "Уведомления отправителю"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
#, fuzzy
msgid "Interval between two top notification checks"
msgstr "Интервал между запросами на деблокирование для доставки"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
#, fuzzy
msgid "Check new versions"
msgstr "Отметить для разрешения этого расширения"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr ""
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Максимальный срок хранения лог записей"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "Срок хранения лог записей в днях "
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Элементов на странице"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Количество элементов на странице"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Порог перенаправления по умолчанию"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr "Если приложение не указано. Используется перенаправление по умолчанию."
-
-#: core/app_settings.py:268
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Ключ должен быть 16, 24 или 32 байта длинной"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Ошибка в написании"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr ""
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Это поле обязательно для заполнеия"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Отображение"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Предпочитаемый язык"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Предпочитаемый язык для отображения страниц"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Логин пользователя"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Пароль"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Старый пароль"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Новый пароль"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Подтверждение"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Старые пароли не совпадают"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Пароли не совпадают"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr ""
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr ""
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Вы не можете удалить собственный аккаунт"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Ошибка обновления пароля: модуль LDAP не установлен"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "Аккаунт"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Ошибочная строка"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "Вы не можете импортировать аккаунт с ролью старше чем у вас"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "Пользователь '%s' должен иметь действительный почтовый адрес"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "Имя пользователя и адрес не должны отличатся для пользователя '%s'"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "Разрешен"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Отметить для разрешения этого расширения"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "добавлено"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "изменено"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s пользователем %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "удалено"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Расширения"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Выберите расширения для использования"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Логин"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Версия"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Описание"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Сохранить"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Информация"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Различная информация о Modoboa"
-
#: core/templates/core/information.html:5
#, fuzzy
msgid "An update is available!"
msgstr "Статистика не доступна"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
@@ -465,145 +330,103 @@ msgid ""
"\">here.\n"
" "
msgstr ""
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "используется в настоящее время"
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Активные пользователи"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Название группы"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Последний вход"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Логи"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Ранее в Modoboa ..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Дата"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Уровень"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Логгер"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Сообщение"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Параметры"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Настройка Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Сохранить"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Настройки Modoboa"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Настройки"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Параметры"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Настроить Modoboa"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Профиль"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Обновить личную информацию"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Обновление"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Завершить сеанс"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Параметры сохранены"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Модификации применены"
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Пользователь '%s' успешно вошел в систему"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "Не правильное имя или пароль. Попробуйте еще раз."
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Пользователь '%s' вышел из системы"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Профиль обновлен"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Параметры сохранены"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Тестовое сообщение"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Отправить вирус"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Отправить спам"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Сообщение отправлено"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -633,2666 +456,132 @@ msgstr ""
"По любым вопросам и с предложениями обращайтесь пожалуйста\n"
" Список "
"рассылки .
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Консоль администратора"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Веб консоль для управления доменами, аккаунтами и синонимами"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr ""
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Домены"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Пользователи"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Перенаправленые"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Ошибка импорта аккаунта (%s): домен должен существовать "
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "Почтовый ящик %s существует"
-
-#: extensions/admin/__init__.py:186
-#, fuzzy, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Ошибка импорта аккаунта (%s): домен должен существовать "
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr ""
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Почтовые ящики"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Обрабатывать почтовые ящики на диске"
-
-#: extensions/admin/app_settings.py:19
-#, fuzzy
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr ""
-"Удалять или переименовывать почтовые ящики на диске, если они удалены или "
-"переименованы в Modoboa"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Почтовые ящики закончились"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "UNIX аккаунт владельца почтового ящика на диске"
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr ""
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr ""
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Автоматическое удаление аккаунта"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr "При удалении почтового ящика, так же удалять и аккаунт владельца"
-
-#: extensions/admin/app_settings.py:49
-#, fuzzy
-msgid "Automatic domain/mailbox creation"
-msgstr "Домен создан"
-
-#: extensions/admin/app_settings.py:52
-msgid "Create a domain and a mailbox when an account is automatically created."
-msgstr ""
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr ""
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr ""
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr ""
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Роль"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Выбрать"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Разрешения для этого пользователя"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Введите такой же пароль как выше. Для проверки."
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Разрешено"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Пароли не совпадают"
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "Вы не можете запретить собственный аккаунт"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "Е-майл"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Квота"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr ""
-"Квота в мегабайтах для этого почтового ящика. Определите собственное "
-"значение или используйте значение по умолчанию для родительского домена. "
-"Оставьте пустым для неограниченного значения. (Не разрешено администраторам "
-"домена)"
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Синоним(ы)"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr ""
-"Синонимы этого почтового ящика. Вводите один адрес за раз. Нажмите ENTER для "
-"добавления. Используйте '*' для создания синонима 'для всех' (*@domain.tld)"
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "Домен не существует"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Домен(ы)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Домен(ы) администрируемые пользователем"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Почта"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Права"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "аккаунт изменен"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Новый аккаунт"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Аккаунт создан"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "Е-майл адрес"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr ""
-"Адрес списка доставки. Используйте символ '*' что бы создать адрес "
-"'доставить всем' Например (*@domain.tld)."
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Получатели"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr ""
-"Этот синоним почтового ящика. Вводите один адрес за раз. Нажмите ENTER для "
-"добавления."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "Вы не имеете права доступа к этому домену"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Неверный почтовый ящик"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Локальный получатель %s не найден"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "Получатель %s уже присутвует"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Получатель не определен"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr ""
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr ""
-"Синоним(ы) этого домена. Вводите одно имя за раз. Нажмите ENTER для "
-"добавления."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr ""
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Создание администратора домена"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Автоматически создаст администратора для этого домена"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr ""
-"Имя администратора. Не включайте имя домена оно будет добавлено "
-"автоматически."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Создание синонимов"
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Автоматически создает стандартные синонимы для этого домена"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Неверный формат"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "Пользователь '%s' уже существует"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Домен изменен"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Опции"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Новый домен"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Домен создан"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Имя файла"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Разделитель"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Получатели"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Укажите одного или нескольких получателей, разделенных запятой ','"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Сохранить локальную копию"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr ""
-"Перенаправление сообщения, и сохранение копии в вашем локальном почтовом "
-"ящике"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr ""
-"Вы не можете определить перенаправление на локальный адрес. Пожалуйста, "
-"попросите администратора создать синоним"
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Выберите файл"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Продолжать при ошибке"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Не исправлять дублирующийся объект при ошибке"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Шифровать пароль"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr "Выберите эту опцию если пароль в вашем файле не зашифрован "
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "адрес"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just "
-"enter an * character."
-msgstr ""
-"Адреса синонимов (без доменной части). Для указания адреса 'для всех' "
-"введите символ *"
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "Почтовые ящики"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "Это синоним почтового ящика"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Синонимы этого синонима указывают на"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Отметить для активации синонима"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "Список рассылки"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "Перенаправление"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "Синоним"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Неверная строка %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "Домен '%s' не существует"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "имя"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "Имя домена"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Отметить для активации этого домена"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr ""
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr ""
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "Имя синонима"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "адресат"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "Домен этого синонима указывает на"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Неизвестный домен %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Адрес почтового ящика (без @domain.tld)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Ошибка получения места находжения почтового ящика (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "Квота больше чем разрешено на уровне домена (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "Требуется квота"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-#, fuzzy
-msgid "Domain is disabled"
-msgstr "Домен удален"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "Мб"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Статистика"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#, fuzzy
-msgid "Domains and identities"
-msgstr "Список пользователей"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr ""
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-#, fuzzy
-msgid "Quantity"
-msgstr "Карантин"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Синонимы доменов"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr ""
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Теги"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Действие"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-#, fuzzy
-msgid "disabled"
-msgstr "Разрешен"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Администраторы"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "Администратор домена не определен"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Дата создания"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Дата последней модификации"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Синонимы почтового ящика"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Автоматически перенаправлять письма на другой адрес"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Полное имя/получатель"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Подсказка"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Импорт..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Выбрать значение"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Используются значения домена по умолчанию "
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Адрес"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Значение"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Лимит"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "использование (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Поиск"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "enabled_m"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "enabled_f"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-#, fuzzy
-msgid "List domains"
-msgstr "Список квот"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Добавить домен"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Импорт"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Экспорт"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Список пользователей"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Список квот"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Добавить аккаунт"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Добавить синоним"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Добавить пересылку"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Добавить список рассылки"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Информация о домене"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "Удалить %s?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Удалить это разрешение"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Синоним с таким именем уже есть"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Создать"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Новый список рассылки"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Список рассылки создан"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Новый синоним"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Синоним создан"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Новая пересылка"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Пересылка создана"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Список рассылки изменен"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Пересылка изменена"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Синоним изменен"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "Вы не можете удалить собственный домен"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Домен удален"
-msgstr[1] "Домена удалено"
-msgstr[2] "Доменов удалено"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Экспорт пользователя"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Экспорт доменов"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Ошибочный запрос"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Аккаунт удален"
-msgstr[1] "Аккаунта удалено"
-msgstr[2] "Аккаунтов удалено"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Импорт доменов"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "Объект уже существует: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d объектов импортировано"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"\n"
-"account; loginname; password; first name; last name; enabled; group; "
-"address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of "
-"the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr ""
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Импорт информации о пользователях"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Перенаправление обновлено"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Простой интерфейс управления AMaViS"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Карантин"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Настройки карантина"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Максимальное время жизни сообщения"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr ""
-"Максимальный срок хранения сообщений в карантине (в днях) перед удалением"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Сообщение деблокировано"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Удалить деблокированные сообщения"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr "Удалить сообщения отмеченные как деблокированные при очистке базы"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Режим подключения Amavis"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Режим подключения к PDP серверу"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "Адрес сервера PDP"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "Адрес PDP сервера (интернет режим)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "Порт сервера PDP"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "Порт PDP сервера (интернет режим)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "Сокет сервера PDP"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Путь к PDP сокету сервера (для UNIX режима)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Разрешить прямое деблокирование"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr ""
-"Позволить пользователю самостоятельно деблокировать сообщения для доставки"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Разрешить режим самообслуживания"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Активировать режим 'самообслуживания'"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Уведомления отправителю"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "Адрес для отправки уведомлений"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:99
-#, fuzzy
-msgid "Default user"
-msgstr "Редактор по умолчанию"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:107
-#, fuzzy
-msgid "Spamd address"
-msgstr "Адрес отправителя"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:113
-#, fuzzy
-msgid "Spamd port"
-msgstr "Импорт"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr ""
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Количество отображаемых сообщений на странице"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Установить максимальное количество сообщений показываемых на странице"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr ""
-
-#: extensions/amavis/forms.py:94
-#, fuzzy
-msgid "Domain's database"
-msgstr "Синонимы доменов"
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr ""
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr ""
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Фильтр содержания"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "Ошибка соединания с Amavis %s"
-
-#: extensions/amavis/lib.py:131
-#, fuzzy
-msgid "No recipient found"
-msgstr "Получатель не определен"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Фильтр вирусов"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "Да"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "Нет"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "По умолчанию"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Обход проверки на вирусы. Выберите 'По умолчанию' для использования "
-"глобальных настроек"
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Спам фильтр"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Обход проверки на спам. Выберите 'По умолчанию' для использования глобальных "
-"настроек"
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Фильтр блокировки"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr ""
-"Обход проверки на блокирование. Выберите 'По умолчанию' для использования "
-"глобальных настроек"
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Спам-метка"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global "
-"settings."
-msgstr ""
-"Изменить тему спам сообщения используя специальный текст. Выберите 'по "
-"умолчанию' для использования глобальных настроек"
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "очистить карантин"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Сообщение удалено"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d сообщение успешно удалено"
-msgstr[1] "%(count)d сообщения успешно удалено"
-msgstr[2] "%(count)d сообщений успешно удалено"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Запрос послан"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Сообщение деблокировано"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d запрос послан"
-msgstr[1] "%(count)d запроса полано"
-msgstr[2] "%(count)d запросов послано"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d сообщение успешно деблокировано"
-msgstr[1] "%(count)d сообщения успешно деблокировано"
-msgstr[2] "%(count)d сообщений успешно деблокировано"
-
-#: extensions/amavis/views.py:360
-#, fuzzy, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d сообщение успешно деблокировано"
-msgstr[1] "%(count)d сообщения успешно деблокировано"
-msgstr[2] "%(count)d сообщений успешно деблокировано"
-
-#: extensions/amavis/views.py:394
-#, fuzzy
-msgid "Select a database"
-msgstr "Выберите файл"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr ""
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Заявки для включения в следующий релиз"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Порог"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "или более это спам"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "или более отклоняет spam сообщение "
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "Кому"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "От кого"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Тема"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-#, fuzzy
-msgid "Released"
-msgstr "Деблокировать"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-#, fuzzy
-msgid "Marked as spam"
-msgstr "Пометить сообщение"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-#, fuzzy
-msgid "Marked as non-spam"
-msgstr "Пометить сообщение"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Управление карантином"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Спам"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Вирус"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Ошибка MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Деблокировать"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Удалить"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-#, fuzzy
-msgid "Mark as spam"
-msgstr "Пометить сообщение"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Все сообщения"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr ""
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] ""
-"\n"
-"%(counter)s запрос на освобождение в процессе выполнения \n"
-msgstr[1] ""
-"\n"
-"%(counter)s запроса на освобождение в процессе выполнения \n"
-msgstr[2] ""
-"\n"
-"%(counter)s запросов на деблокирование в процессе выполнения \n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Эскиз:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "От кого:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "Кому:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Дата:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Тема:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Действуйте согласно этого сообщения"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Для просмотра листинга посетите %(listingurl)s"
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Назад"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Просмотр заголовков"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr "Лимиты для администраторов на количество создаваемых объектов"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Лимиты"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Лимиты по умолчанию"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Администраторы домена"
-
-#: extensions/limits/app_settings.py:15
-msgid "Maximum number of allowed domain administrators for a new administrator"
-msgstr ""
-"Максимальное количество администраторов домена для нового администратора"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Максимальное количество доменов для нового администратора"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr "Максимальное количество синонимов доменов для нового администратора"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Максимальное количество почтовых ящиков для нового администратора"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Максимальное количество синонимов для нового администратора"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Ошибочный лимит"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Ваши ресурсы не инициализированы"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "Вам не позволено определять нелимитированные значения"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Реселлер"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Ресурсы"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s лимит исчерпан"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Недостаточно ресурсов"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr ""
-"Максимальное количество создаваемых администраторов домена для этого "
-"пользователя"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Максимальное количество создаваемых доменов для этого пользователя"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr ""
-"Максимальное количество создаваемых синонимов (алиасов) доменов для этого "
-"пользователя"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr ""
-"Максимальное количество создаваемых почтовых ящиков для этого пользователя"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr ""
-"Максимальное количество создаваемых синонимов почтовых ящиков для этого "
-"пользователя"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "Не определено"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "Не лимитировано"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Использование ресурсов"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Автоответчик (отпуск) использует возможности PostFix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Автоматические ответы"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Тайм-аут автоматического ответа"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr "Промежуток между автоматическими ответами"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr ""
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr ""
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Утилиты"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Активировать автоответчик после даты"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Эта дата позже"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr ""
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Сообщение автоответчика"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr ""
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr ""
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "Тема"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "Тема отправляемых сообщений"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "Содержание"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "Содержание отправляемых сообщений"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Активировать/Деактивировать автоответчик"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Сообщения автоответчика успешно обновлены"
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr "Задает сообщение для автоматической отправки при вашем отсутствии"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr ""
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr ""
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr ""
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr ""
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients"
-"em> \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr ""
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr ""
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr ""
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr ""
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr ""
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr ""
-
-#: extensions/radicale/__init__.py:34
-#, fuzzy
-msgid "Radicale management"
-msgstr "Управление карантином"
-
-#: extensions/radicale/__init__.py:38
-msgid "Management frontend for Radicale, a simple calendar and contact server."
-msgstr ""
-
-#: extensions/radicale/app_settings.py:11
-#, fuzzy
-msgid "Server settings"
-msgstr "Настройки фильтров содержания"
-
-#: extensions/radicale/app_settings.py:15
-#, fuzzy
-msgid "Server URL"
-msgstr "Порт сервера"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr ""
-
-#: extensions/radicale/app_settings.py:24
-#, fuzzy
-msgid "Rights management"
-msgstr "Управление карантином"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr ""
-
-#: extensions/radicale/app_settings.py:36
-#, fuzzy
-msgid "Allow calendars administration"
-msgstr "Администратор домена"
-
-#: extensions/radicale/app_settings.py:39
-#, fuzzy
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr ""
-"Максимальное количество создаваемых администраторов домена для этого "
-"пользователя"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr ""
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr ""
-
-#: extensions/radicale/forms.py:134
-#, fuzzy, python-format
-msgid "Mailbox %s does not exist"
-msgstr "Домен '%s' не существует"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr ""
-
-#: extensions/radicale/forms.py:162
-#, fuzzy
-msgid "New calendar"
-msgstr "Новый синоним"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-#, fuzzy
-msgid "Calendar created"
-msgstr "Фильтр создан"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-#, fuzzy
-msgid "Calendar updated"
-msgstr "Профиль обновлен"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr ""
-
-#: extensions/radicale/models.py:94
-#, fuzzy
-msgid "User"
-msgstr "Логин пользователя"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr ""
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-#, fuzzy
-msgid "Calendar removed"
-msgstr "Фильтр удален"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr ""
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr ""
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr ""
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-#, fuzzy
-msgid "Add calendar"
-msgstr "Добавить синоним"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr ""
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr ""
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Плагин позволяет создавать фильтры на сервере"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "Фильтры содержания"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Фильтры сообщений"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "Настройки фильтров содержания"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Адрес вашего MANAGESIEVE сервера"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "Порт вашего MANAGESIEVE сервера"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Подключение с помощью STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Используйте расширение STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Механизм аутентификации"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Предпочтительный механизм аутентификации"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Режим редактирования"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Выберите нужный режим для работы редактора"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Проверьте, чтобы активировать этот набор фильтров"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Любое из следующих"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Любое из следующих"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "содержит"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "не содержит"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "является"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "не"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Отправитель"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Получатель"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Копия"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "размер"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "больше"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "меньше"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Переместить сообщение"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Перенаправление сообщение для"
-
-#: extensions/sievefilters/forms.py:110
-#, fuzzy
-msgid "Wrong filter name"
-msgstr "Имя файла"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr "Соединение с сервером MANAGESIEVE не удалось, проверьте конфигурацию"
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Нет свободного места на сервере"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Не удалось получить набор фильтров"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Новый фильтр"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Фильтр создан"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Редактировать фильтр"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Фильтр модифицирован"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Фильтр удален"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Ошибка удаления фильтра"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Набор фильтров сохранен"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Набор фильтров создан"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Создание нового набора фильтров"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Набор фильтров удален"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Набор фильтров активирован"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Соответствие"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Активно"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Фильтры не определены"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Набор фильтров"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "Активно"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr "Фильтры не определены. Вы должны определить и установить фильтры "
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Новый набор фильтров"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Сохранить набор фильтров"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Активировать набор фильтров"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Удалить набор фильтров"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Загрузить"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Удалить этот фильтр"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Переместить этот фильтр выше"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Переместить этот фильтр ниже"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Графическая статистика о почтовом траффика использует RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Графическая статистика"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Путь к лог файлу"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Путь к лог файлу для сбора статистики"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Папка для сохранения RRD файлов"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Путь к директории для сохранения RRD файлов"
-
-#: extensions/stats/graphics.py:98
-#, fuzzy
-msgid "Average traffic (msgs/min)"
-msgstr "Средний размер траффика"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "Отправлено сообщений"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "Принято сообщений"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "Возвращенные сообщения"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "Отвергнутые сообщения"
-
-#: extensions/stats/graphics.py:112
-#, fuzzy
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Средний размер траффика"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "Принято"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "Отправлено"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Почтовый траффик"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Статистика не доступна"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "День"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Неделя"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Месяц"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "Год"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr ""
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Неизвестный графический набор "
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Не верный выбор периода"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Искать домен"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Применить"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Веб-почта простой IMAP"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Максимальный размер вложения"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Максимальный размер вложения в байтах (или КБ. МБ, ГБ)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "Настройки IMAP"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Адрес вашего IMAP сервера"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Использовать защищенное соединение с IMAP севером"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "Порт вашего IMAP сервера"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "Настройки SMTP"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Адрес вашего сервера SMTP"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Режим безопасного подключения"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Нет"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Использовать защищенное соединение"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "Порт вашего SMTP сервера"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Требуется аутентификация"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "Сервер требует авторизации"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Отображение сообщений по умолчанию"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "Для отображения сообщения используется режим по умолчанию"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Разрешить показ HTML ссылок"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Разрешить/Запретить показ HTML ссылок"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Максимальное количество сообщений на страницу"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Частота обновления листинга"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Время обновления папок в секундах"
-
-#: extensions/webmail/app_settings.py:103
-#, fuzzy
-msgid "Mailboxes container's width"
-msgstr "Почтовые ящики закончились"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr ""
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Корзина"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Папка для удаленных сообщений"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Папка отправленные"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Папка для копий отправленных сообщений"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Папка для черновиков"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Папка для черновиков"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Написать сообщение"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Редактор по умолчанию"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "Редактор по умолчанию для создания сообщения"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Тест подписи"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Пользовательская подпись "
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr ""
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Ответ сервера"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Неизвестное действие"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "Скрытая копия"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Веб-почта"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d сообщение удалено"
-msgstr[1] "%(count)d сообщения удалено"
-msgstr[2] "%(count)d сообщений удалено"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Очистить почтовый ящик"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Почтовый ящик создан"
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Создать новый почтовый ящик"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Изменить почтовый ящик"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Почтовый ящик обновлен"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Ошибка записи вложения:"
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "Вложения слишком велики (лимит: %s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Вложения"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Ошибочный запрос"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Не удалось удалить вложение"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Неизвестное вложение"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "Пишет:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "исходное сообщение"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Не удалось получить разделитель уровней иерархии"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "Подключение к IMAP серверу не удалось: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Вложить"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Загрузка..."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Родительский почтовый ящик"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr ""
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Ответить"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Ответить всем"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Показать параметры"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Разрешить ссылки"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Запретить ссылки"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Послать"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-#, fuzzy
-msgid "Mark as read"
-msgstr "Пометить сообщение"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-#, fuzzy
-msgid "Mark as unread"
-msgstr "Как не прочтенное"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Очистить папку"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Изменить выбранный почтовый ящик"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Удалить выбранный почтовый ящик"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Сжать папку"
-
-#: lib/dbutils.py:36
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Сообщение отправлено"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr ""
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "В разрешении отказано: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "В разрешении отказано"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr ""
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Ошибочный запрос"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Введите действительный адрес домена"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Да"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "Нет"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Ошибка обновления пароля: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Обычный пользователь"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Супер администратор"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Администратор домена"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Жаль"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "Запрошенная станица не существует"
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Внутренняя ошибка"
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Поиск..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Адрес отправителя"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Тема"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Оба"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Ошибка:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Подсказка:"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Закрыть"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Предыдущая"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Следующая"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Добро пожаловать в Modoboa!"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Запомнить меня"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Войти"
-
#, fuzzy
-#~ msgid "Server location"
-#~ msgstr "Порт сервера"
-
-#~ msgid "Filter"
-#~ msgstr "Фильтр"
-
-#~ msgid "Check requests interval"
-#~ msgstr "Интервал проверки запросов"
-
-#~ msgid "pending requests"
-#~ msgstr "ожидающие запросы"
-
-#~ msgid "Average normal traffic"
-#~ msgstr "Средний нормальный траффик"
-
-#~ msgid "msgs/min"
-#~ msgstr "сообщений/в мин"
-
-#~ msgid "Average bad traffic"
-#~ msgstr "Средний ошибочный траффик"
-
-#~ msgid "bytes/min"
-#~ msgstr "байт/в мин"
-
-#~ msgid "Total"
-#~ msgstr "Итого"
-
-#~ msgid "Predefined time ranges"
-#~ msgstr "Предопределенные временные диапазоны"
-
-#~ msgid "Custom time range"
-#~ msgstr "Пользовательские временные диапазоны"
-
-#~ msgid "Add Cc field"
-#~ msgstr "Добавить поле для невидимой копии"
-
-#~ msgid "Add Cci field"
-#~ msgstr "Добавить поле для невидимой копии"
-
-#~ msgid "%(counter)s file"
-#~ msgid_plural "%(counter)s files"
-#~ msgstr[0] "%(counter)s файл"
-#~ msgstr[1] "%(counter)s файла"
-#~ msgstr[2] "%(counter)s файлов"
-
-#~ msgid "Mailbox quota"
-#~ msgstr "Квота для почтового ящика"
-
-#~ msgid "Close this message"
-#~ msgstr "Закрыть это сообщение"
-
-#~ msgid "New message"
-#~ msgstr "Новое сообщение"
-
-#~ msgid "Mark messages"
-#~ msgstr "Пометить сообщение"
-
-#~ msgid "As read"
-#~ msgstr "как прочтенное"
-
-#~ msgid "No entries to display"
-#~ msgstr "Нет данных для отображения"
-
-#~ msgid "activate"
-#~ msgstr "Активировать"
-
-#~ msgid "Powered by Modoboa"
-#~ msgstr "На базе Modoboa"
-
-#~ msgid "Directory to store PNG files"
-#~ msgstr "Папка для сохранения PNG файлов"
-
-#~ msgid "Path to directory where PNG files are stored"
-#~ msgstr "Путь к директории для сохранения png файлов"
-
-#~ msgid "Failed to grant access (%s)"
-#~ msgstr "Не удалось предоставить доступ (%s)"
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
+#, fuzzy
diff --git a/modoboa/locale/ru/LC_MESSAGES/djangojs.po b/modoboa/locale/ru/LC_MESSAGES/djangojs.po
index f2bc27f56..f892f590e 100644
--- a/modoboa/locale/ru/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/ru/LC_MESSAGES/djangojs.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2013-12-03 09:35+0000\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: Russian (http://www.transifex.com/projects/p/modoboa/language/"
@@ -18,182 +18,26 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "Не удаляйте каталог домена"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Эта операция удалит ВСЕ данные, связанные с этим доменом."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr ""
-"Эта операция удалит ВСЕ данные, связанные с этим доменом, за исключением "
-"аккаунтов."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Не указан администратор домена"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr ""
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Не удаляйте каталог почтовых ящиков"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Деблокировать отмеченные?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Удалить отмеченные?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-#, fuzzy
-msgid "Mark this selection as spam?"
-msgstr "Деблокировать отмеченные?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-#, fuzzy
-msgid "Mark this selection as non-spam?"
-msgstr "Деблокировать отмеченные?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Деблокировать сообщение?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Удалить сообщение?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr ""
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Просмотр всех заголовков"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Скрыть все заголовки"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr ""
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr ""
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Удалить фильтр?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Сохранить изменения?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Удалить набор фильтров?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Активировать набор фильтров?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "активно"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Найти домен"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr ""
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Удалить выбранные почтовые ящики?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Почтовый ящик удален"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Сообщение послано"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "Перемещается %s сообщение"
-msgstr[1] "Перемещается %s сообщения"
-msgstr[2] "Перемещается %s сообщений"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Внимание"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Отмена"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr ""
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr ""
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Поиск"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Поиск..."
-
-#~ msgid "%s file"
-#~ msgid_plural "%s files"
-#~ msgstr[0] "%s файл"
-#~ msgstr[1] "%s файла"
-#~ msgstr[2] "%s файлов"
-
-#~ msgid "Message deleted"
-#~ msgstr "Сообщение удалено"
+#, fuzzy
+#, fuzzy
diff --git a/modoboa/locale/sv/LC_MESSAGES/django.po b/modoboa/locale/sv/LC_MESSAGES/django.po
index ef14bf116..3dcee91d4 100644
--- a/modoboa/locale/sv/LC_MESSAGES/django.po
+++ b/modoboa/locale/sv/LC_MESSAGES/django.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Martin Persson , 2014
# Olle Gustafsson , 2013
@@ -10,3092 +10,546 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-12-04 13:25+0100\n"
+"POT-Creation-Date: 2015-02-11 15:06+0100\n"
"PO-Revision-Date: 2015-01-13 15:18+0000\n"
"Last-Translator: Olle Gustafsson \n"
-"Language-Team: Swedish (http://www.transifex.com/projects/p/modoboa/language/sv/)\n"
+"Language-Team: Swedish (http://www.transifex.com/projects/p/modoboa/language/"
+"sv/)\n"
+"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: sv\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: core/__init__.py:56 core/__init__.py:57
-#: extensions/admin/forms/account.py:366 extensions/admin/forms/account.py:443
-#: extensions/admin/forms/domain.py:271 extensions/admin/forms/domain.py:332
-#: extensions/postfix_autoreply/app_settings.py:11
-#: extensions/postfix_relay_domains/app_settings.py:18
-#: extensions/postfix_relay_domains/forms.py:150
-#: extensions/radicale/forms.py:155 extensions/radicale/forms.py:185
-#: extensions/sievefilters/app_settings.py:53
-#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11
+#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Generellt"
-
-#: core/__init__.py:86
+#: core/__init__.py:84
msgid "New Modoboa version available"
msgstr "En ny version av Modoboa är tillgänglig"
-
-#: core/app_settings.py:39
+#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autentisering"
-
-#: core/app_settings.py:42
+#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Autentiseringstyp"
-
-#: core/app_settings.py:43
+#: core/app_settings.py:38
msgid "Local"
msgstr "Lokal"
-
-#: core/app_settings.py:46
+#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Autentiserings backend"
-
-#: core/app_settings.py:51
+#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Standard lösenords schema"
-
-#: core/app_settings.py:54
+#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (svag)"
-
-#: core/app_settings.py:55
+#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (svag)"
-
-#: core/app_settings.py:56
+#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (svag)"
-
-#: core/app_settings.py:57
+#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (svag)"
-
-#: core/app_settings.py:58
+#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "okrypterad (svag)"
-
-#: core/app_settings.py:60
+#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Krypteringsschema för brevlåde lösenord"
-
-#: core/app_settings.py:65
+#: core/app_settings.py:60
msgid "Rounds"
msgstr "Antal omgångar"
-
-#: core/app_settings.py:68
+#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
-msgstr "Antal omgångar att använda (används endast av sha256crypt och sha512crypt). Måste vara mellan 1000 och 999999999."
-
-#: core/app_settings.py:75
+msgstr ""
+"Antal omgångar att använda (används endast av sha256crypt och sha512crypt). "
+"Måste vara mellan 1000 och 999999999."
+#: core/app_settings.py:70
msgid "Secret key"
msgstr "Hemlig nyckel"
-
-#: core/app_settings.py:77
+#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Nyckel som används för att kryptera / dekryptera lösenord"
-
-#: core/app_settings.py:82
+#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "LDAP inställningar"
-
-#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:22
-#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42
+#: core/app_settings.py:80
msgid "Server address"
msgstr "Server adress"
-
-#: core/app_settings.py:88
+#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "IP adressen eller DNS namn för LDAP server"
-
-#: core/app_settings.py:93 extensions/sievefilters/app_settings.py:29
-#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58
+#: core/app_settings.py:88
msgid "Server port"
msgstr "Server port"
-
-#: core/app_settings.py:95
+#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "TCP port som används av LDAP servern"
-
-#: core/app_settings.py:100 extensions/webmail/app_settings.py:28
+#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Använd en säker anslutning"
-
-#: core/app_settings.py:103
+#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Använd SSL/TLS anslutning för åtkomst till LDAP servern"
-
-#: core/app_settings.py:107
+#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Autentiseringsmetod"
-
-#: core/app_settings.py:108
+#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Sök och bind"
-
-#: core/app_settings.py:109
+#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Direkt bindning"
-
-#: core/app_settings.py:111
+#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Välj autentiseringsmetod att använda"
-
-#: core/app_settings.py:116
+#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Bind DN"
-
-#: core/app_settings.py:119
+#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
-msgstr "Det unika namnet för att använda vid bindningar till LDAP-servern. Lämna tomt för en anonym bindning"
-
-#: core/app_settings.py:127
+msgstr ""
+"Det unika namnet för att använda vid bindningar till LDAP-servern. Lämna "
+"tomt för en anonym bindning"
+#: core/app_settings.py:122
msgid "Bind password"
msgstr "Bind lösenord"
-
-#: core/app_settings.py:130
+#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
-msgstr "Lösenordet ska användas vid bindning till LDAP-servern (med \"Bind DN ')"
-
-#: core/app_settings.py:139
+msgstr ""
+"Lösenordet ska användas vid bindning till LDAP-servern (med \"Bind DN ')"
+#: core/app_settings.py:134
msgid "Users search base"
msgstr "Användare sökbas"
-
-#: core/app_settings.py:142
+#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "Det unika namnet för sökbasen som används för att hitta användare"
-
-#: core/app_settings.py:149
+#: core/app_settings.py:144
msgid "Search filter"
msgstr "Sökfilter"
-
-#: core/app_settings.py:152
+#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
-msgstr "En valfri filtersträng (t.ex. \"(objectClass = personer) '). För att vara giltigt måste det omges av parenteser."
-
-#: core/app_settings.py:160
+msgstr ""
+"En valfri filtersträng (t.ex. \"(objectClass = personer) '). För att vara "
+"giltigt måste det omges av parenteser."
+#: core/app_settings.py:155
msgid "User DN template"
msgstr "Anvädar DN mall"
-
-#: core/app_settings.py:163
+#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
"placeholder (ie. %(user)s)"
-msgstr "Mallen som används för att konstruera en användares DN. Den bör innehålla en platshållare (dvs. %(user)s)"
-
-#: core/app_settings.py:171
+msgstr ""
+"Mallen som används för att konstruera en användares DN. Den bör innehålla en "
+"platshållare (dvs. %(user)s)"
+#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Lösenordsattribut"
-
-#: core/app_settings.py:173
+#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Attribut som används för att lagra användarlösenord"
-
-#: core/app_settings.py:178
+#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
-
-#: core/app_settings.py:181
+#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Berätta om LDAP-servern är en Active Directory"
-
-#: core/app_settings.py:185
+#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Administratörsgrupper"
-
-#: core/app_settings.py:188
+#: core/app_settings.py:183
msgid ""
-"Members of those LDAP Posix groups will be created as domain administrators."
-" Use ';' characters to separate groups."
-msgstr "Användare av dessa LDAP Posix grupper kommer skapas som domänadministratörer. Använd ';' för att separera grupper."
-
-#: core/app_settings.py:195
+"Members of those LDAP Posix groups will be created as domain administrators. "
+"Use ';' characters to separate groups."
+msgstr ""
+"Användare av dessa LDAP Posix grupper kommer skapas som "
+"domänadministratörer. Använd ';' för att separera grupper."
+#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Grupper sökbas"
-
-#: core/app_settings.py:198
+#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "Det unika namnet för sökbasen som används för att hitta grupper"
-
-#: core/app_settings.py:203
-#: extensions/admin/templates/admin/editdomainform.html:7
+#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Övrigt"
-
-#: core/app_settings.py:206
+#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Toppnotifikationer kontrollintervall"
-
-#: core/app_settings.py:208
+#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Intervall mellan två toppnotifikation kontroller"
-
-#: core/app_settings.py:213
+#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Kontrollera nya versioner"
-
-#: core/app_settings.py:216
+#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Kontrollera automatiskt om en nyare version finns"
-
-#: core/app_settings.py:220
+#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Maximal ålder för loggpost"
-
-#: core/app_settings.py:222
+#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "Maximal ålder i dagar för en logg post"
-
-#: core/app_settings.py:227
+#: core/app_settings.py:222
msgid "Items per page"
msgstr "Artiklar per sida"
-
-#: core/app_settings.py:229
+#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Antal poster som visas per sida"
-
-#: core/app_settings.py:234
+#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Standard topp omdirigering"
-
-#: core/app_settings.py:238
+#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr "Standard omdirigering när ingen applikation angetts"
-
-#: core/app_settings.py:268
+#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Nyckel måste vara endera 16, 24 eller 32 bytes lång"
-
-#: core/app_settings.py:277 extensions/postfix_autoreply/app_settings.py:55
+#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Ogiltig syntax"
-
-#: core/app_settings.py:283
+#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Ogiltigt antal omgångar"
-
-#: core/app_settings.py:306
+#: core/app_settings.py:299
msgid "This field is required"
msgstr "Detta fält är obligatoriskt"
-
-#: core/app_settings.py:368 extensions/amavis/app_settings.py:156
-#: extensions/amavis/templates/amavis/main_action_bar.html:51
-#: extensions/webmail/app_settings.py:73
+#: core/app_settings.py:367
msgid "Display"
msgstr "Visning"
-
-#: core/app_settings.py:372
+#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Önskat språk"
-
-#: core/app_settings.py:378
+#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Önskat språk för att visa sidor"
-
-#: core/forms.py:10 extensions/admin/forms/account.py:21
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/radicale/forms.py:69
+#: core/forms.py:14
msgid "Username"
msgstr "Användarnamn"
-
-#: core/forms.py:14 extensions/admin/forms/account.py:33
+#: core/forms.py:18
msgid "Password"
msgstr "Lösenord"
-
-#: core/forms.py:25
+#: core/forms.py:29
msgid "Old password"
msgstr "Gammalt lösenord"
-
-#: core/forms.py:29
+#: core/forms.py:33
msgid "New password"
msgstr "Nytt lösenord"
-
-#: core/forms.py:33 extensions/admin/forms/account.py:36
+#: core/forms.py:37
msgid "Confirmation"
msgstr "Bekräftelse"
-
-#: core/forms.py:60
+#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Gammalt lösenord matchar inte"
-
-#: core/forms.py:65
+#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Lösenord matchar inte"
-
-#: core/models.py:50
+#: core/models.py:52
msgid "password"
msgstr "lösenord"
-
-#: core/models.py:52
+#: core/models.py:54
msgid "last login"
msgstr "senaste inloggning"
-
-#: core/models.py:81
+#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Du kan inte radera ditt eget konto"
-
-#: core/models.py:130
+#: core/models.py:132
msgid "Failed to update password: LDAP module not installed"
msgstr "Misslyckades med att uppdatera lösenord: LDAP modul ej installerad"
-
-#: core/models.py:183
+#: core/models.py:185
msgid "account"
msgstr "konto"
-
-#: core/models.py:334 extensions/admin/models/domain.py:149
-#: extensions/admin/models/domain_alias.py:39
-#: extensions/postfix_relay_domains/models.py:134
-#: extensions/postfix_relay_domains/models.py:190
+#: core/models.py:338
msgid "Invalid line"
msgstr "Ogiltig rad"
-
-#: core/models.py:338
+#: core/models.py:343
msgid "You can't import an account with a role greater than yours"
msgstr "Du kan inte importera konto med en roll större än din"
-
-#: core/models.py:350
+#: core/models.py:355
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "Den enkla användaren '%s' måste ha en gällande e-postadress"
-
-#: core/models.py:354
+#: core/models.py:360
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "användarnamn och e-post fält får inte avvika för '%s'"
-
-#: core/models.py:426 extensions/admin/models/alias.py:35
-#: extensions/admin/models/domain.py:32
-#: extensions/admin/models/domain_alias.py:17
-#: extensions/postfix_autoreply/models.py:28
-#: extensions/postfix_relay_domains/models.py:85
-#: extensions/postfix_relay_domains/models.py:167
-msgid "enabled"
-msgstr "aktiverad"
-
-#: core/models.py:427
-msgid "Check to enable this extension"
-msgstr "Markera för att aktivera detta tillägg"
-
-#: core/models.py:511
+#: core/models.py:461
msgid "added"
msgstr "tillagd"
-
-#: core/models.py:514
+#: core/models.py:464
msgid "modified"
msgstr "ändrad"
-
-#: core/models.py:516 core/models.py:541
+#: core/models.py:466 core/models.py:491
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s av användare %(user)s"
-
-#: core/models.py:543
+#: core/models.py:493
msgid "deleted"
msgstr "raderad"
-
-#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48
+#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
msgid "Extensions"
msgstr "Tillägg"
-
-#: core/templates/core/extensions.html:2
-msgid "Choose the extension(s) to use"
+#: core/templates/core/extensions.html:4
+#, fuzzy
+#| msgid "Choose the extension(s) to use"
+msgid "The extension(s) you are using"
msgstr "Välj tillägg att aktivera"
-
-#: core/templates/core/extensions.html:9
-#: core/templates/core/information.html:16 extensions/admin/tables.py:9
-#: extensions/admin/forms/domain.py:190
-#: extensions/admin/templates/admin/domains.html:25
-#: extensions/admin/templates/admin/editdomainform.html:13
-#: extensions/admin/templates/admin/identity_headers.html:2
-#: extensions/radicale/templates/radicale/calendars.html:48
-#: extensions/sievefilters/forms.py:66
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:6
+#: core/templates/core/extensions.html:8
+#: core/templates/core/information.html:16
msgid "Name"
msgstr "Namn"
-
-#: core/templates/core/extensions.html:10 extensions/admin/tables.py:11
+#: core/templates/core/extensions.html:9
msgid "Version"
msgstr "Version"
-
-#: core/templates/core/extensions.html:11 extensions/admin/tables.py:13
+#: core/templates/core/extensions.html:10
msgid "Description"
msgstr "Beskrivning"
-
-#: core/templates/core/extensions.html:26
-#: core/templates/core/parameters.html:6
-#: core/templates/core/user_preferences.html:8
-msgid "Save"
-msgstr "Spara"
-
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
msgid "Information"
msgstr "Information"
-
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Uppgifter om Modoboa"
-
#: core/templates/core/information.html:5
msgid "An update is available!"
msgstr "En uppdatering finns tillgänglig!"
-
#: core/templates/core/information.html:6
#, python-format
msgid ""
"\n"
-" Modoboa %(version)s is available for download. The list of all changes is available here .\n"
+" Modoboa %(version)s is available for download. The list "
+"of all changes is available here .\n"
+" "
+msgstr ""
+"\n"
+" Modoboa %(version)s finsn för nedladdning. Lista över "
+"förändringar finns här .\n"
" "
-msgstr "\n Modoboa %(version)s finsn för nedladdning. Lista över förändringar finns här .\n "
-
#: core/templates/core/information.html:11
msgid "is currently in use."
msgstr "används för närvarande."
-
#: core/templates/core/information.html:13
msgid "Active users"
msgstr "Aktiva användare"
-
#: core/templates/core/information.html:17
msgid "Group name"
msgstr "Gruppnamn"
-
#: core/templates/core/information.html:18
msgid "Last login"
msgstr "Senaste inloggad"
-
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
msgid "Logs"
msgstr "Loggar"
-
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Tidigare på Modoboa..."
-
#: core/templates/core/logs.html:6
-#: extensions/amavis/templates/amavis/email_list.html:23
-#: extensions/webmail/lib/imapemail.py:300
msgid "Date"
msgstr "Datum"
-
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Nivå"
-
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Loggare"
-
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Meddelande"
-
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
msgid "Parameters"
msgstr "Parametrar"
-
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Konfigurera Modoboa"
-
+#: core/templates/core/parameters.html:6
+#: core/templates/core/user_preferences.html:8
+msgid "Save"
+msgstr "Spara"
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Modoboa inställningar"
-
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:81
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
msgid "Settings"
msgstr "Inställningar"
-
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:108
+#: core/templatetags/core_tags.py:112
msgid "Preferences"
msgstr "Inställningar"
-
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Anpassa Modoboa"
-
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
msgid "Profile"
msgstr "Profil"
-
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Uppdatera personlig information"
-
-#: core/templates/core/user_profile.html:8
-#: extensions/admin/templates/admin/forward.html:9
-#: extensions/admin/views/alias.py:108
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9
-#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:186
-#: extensions/webmail/views.py:221 lib/formutils.py:322
+#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Uppdatera"
-
-#: core/templatetags/core_tags.py:21
+#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-
-#: core/templatetags/core_tags.py:90
+#: core/templatetags/core_tags.py:94
msgid "Logout"
msgstr "Logga ut"
-
-#: core/views/admin.py:54
+#: core/views/admin.py:51
msgid "Parameters saved"
msgstr "Parametrar sparade"
-
-#: core/views/admin.py:99
-msgid "Modifications applied."
-msgstr "Modifieringar tillämpade."
-
-#: core/views/auth.py:30
+#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Användare '%s' har loggat in"
-
-#: core/views/auth.py:44
+#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "Ditt användarnamn och lösenord matchar inte. Var vänlig försök igen."
-
-#: core/views/auth.py:72
+#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Användare '%s' har loggat ut"
-
-#: core/views/user.py:35
+#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profil uppdaterad"
-
-#: core/views/user.py:58
+#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Inställningar sparade"
-
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Test meddelande"
-
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Skicka virus"
-
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Skicka skräppost"
-
-#: demo/views.py:19 demo/views.py:45
-msgid "Message sent"
-msgstr "Meddelande sänt"
-
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
"Welcome to the online demo! \n"
"Warning: the demo's concent is resetted every two hours.
\n"
-"To try the demo, the following users are available (username/password ):
\n"
+"To try the demo, the following users are available (username/password"
+"i>):
\n"
"\n"
" A super administrator : admin/password \n"
" A domain administrator : admin@demo.local/admin \n"
" A simple user : user@demo.local/user \n"
" \n"
"Please report any issue or give any suggestion to \n"
-" the mailing list .
\n"
-msgstr "\nVälkommen till online-demot! \nVarning: demots innehåll återställs varannan timme
\nFör att prova demot, följande användare finns tillgängliga (användarnamn/lösenord ):
\n\nEn super administratör: admin/password \nEn domän administratölr: admin@demo.local/admin \nEn enkel användare: user@demo.local/user \n \nVar vänlig rapportera eventuella fel eller ge förslag på mailinglistan .
\n"
-
-#: extensions/admin/__init__.py:48
-msgid "Administration console"
-msgstr "Administrerings konsoll"
-
-#: extensions/admin/__init__.py:51
-msgid "Web based console to manage domains, accounts and aliases"
-msgstr "Webbaserad konsoll för att hantera domäner, konton och alias"
-
-#: extensions/admin/__init__.py:57
-msgid "Administration"
-msgstr "Administration"
-
-#: extensions/admin/__init__.py:85
-#: extensions/admin/templates/admin/domain_statistics.html:30
-#: extensions/admin/templates/admin/domains.html:3
-#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17
-msgid "Domains"
-msgstr "Domäner"
-
-#: extensions/admin/__init__.py:91
-#: extensions/admin/templates/admin/domain_statistics.html:36
-#: extensions/admin/templates/admin/domain_statistics.html:50
-#: extensions/admin/templates/admin/identities.html:5
-msgid "Identities"
-msgstr "Konton"
-
-#: extensions/admin/__init__.py:106
-#: extensions/admin/templates/admin/forward.html:2
-#: extensions/webmail/templatetags/webmail_tags.py:38
-msgid "Forward"
-msgstr "Vidarebefordra"
-
-#: extensions/admin/__init__.py:169
-#, python-format
-msgid "Account import failed (%s): domain does not exist"
-msgstr "Konto import misslyckades (%s): domänen existerar inte"
-
-#: extensions/admin/__init__.py:178 extensions/admin/forms/account.py:225
-#, python-format
-msgid "Mailbox %s already exists"
-msgstr "Brevlåda %s finns redan"
-
-#: extensions/admin/__init__.py:186
-#, python-format
-msgid "Account import failed (%s): wrong quota value"
-msgstr "Importering av konto misslyckades (%s): Fel kvota värde"
-
-#: extensions/admin/__init__.py:218 extensions/admin/forms/domain.py:84
-#: extensions/postfix_relay_domains/forms.py:61
-#: extensions/postfix_relay_domains/forms.py:81
-msgid "domain alias"
-msgstr "domän alias"
-
-#: extensions/admin/app_settings.py:13
-#: extensions/admin/templates/admin/editdomainform.html:25
-#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23
-#: extensions/webmail/app_settings.py:107
-msgid "Mailboxes"
-msgstr "Brevlådor"
-
-#: extensions/admin/app_settings.py:16
-msgid "Handle mailboxes on filesystem"
-msgstr "Hantera brevlådor på filsystem"
-
-#: extensions/admin/app_settings.py:19
-msgid ""
-"Rename or remove mailboxes on the filesystem when they get renamed or "
-"removed within Modoboa"
-msgstr "Byt namn på eller ta bort brevlådor på filsystemet när de kommer byta namn eller tas bort inom Modoboa"
-
-#: extensions/admin/app_settings.py:25
-msgid "Mailboxes owner"
-msgstr "Brevlådans ägare"
-
-#: extensions/admin/app_settings.py:28
-msgid "The UNIX account who owns mailboxes on the filesystem"
-msgstr "Den UNIX-konto som äger brevlådor på filsystemet"
-
-#: extensions/admin/app_settings.py:33
-msgid "Default domain quota"
-msgstr "Standard domän kvota"
-
-#: extensions/admin/app_settings.py:36
-msgid ""
-"Default quota (in MB) applied to freshly created domains with no value "
-"specified. A value of 0 means no quota."
-msgstr "Standard kvota (i MB) applicerad på nyskapade domäner som inte har något värde specificerat. Ett värde på 0 betyder ingen kvota."
-
-#: extensions/admin/app_settings.py:42
-msgid "Automatic account removal"
-msgstr "Automatisk konto borttagning"
-
-#: extensions/admin/app_settings.py:45
-msgid "When a mailbox is removed, also remove the associated account"
-msgstr "När en brevlåda raderas, radera också tillhörande konto"
-
-#: extensions/admin/app_settings.py:49
-msgid "Automatic domain/mailbox creation"
-msgstr "Automatisk skapande av domän/brevlåda"
-
-#: extensions/admin/app_settings.py:52
-msgid ""
-"Create a domain and a mailbox when an account is automatically created."
-msgstr "Skapa en domän och en brevlåda när ett konto skapas automatiskt."
-
-#: extensions/admin/app_settings.py:98 extensions/admin/forms/account.py:206
-#: extensions/admin/forms/domain.py:66
-msgid "Must be a positive integer"
-msgstr "Måste vara ett positivt heltal"
-
-#: extensions/admin/lib.py:27
-msgid "A mailbox is required"
-msgstr "En brevlåda krävs"
-
-#: extensions/admin/forms/account.py:23
-msgid ""
-"The user's name. Must be a valid e-mail address for simple users or "
-"administrators with a mailbox."
-msgstr "Användarens namn. Måste vara en giltig e-postadress för vanliga användare eller för administratörer med brevlåda."
-
-#: extensions/admin/forms/account.py:28
-msgid "Role"
-msgstr "Roll"
-
-#: extensions/admin/forms/account.py:29 extensions/admin/forms/account.py:60
-msgid "Choose"
-msgstr "Välj"
-
-#: extensions/admin/forms/account.py:30
-msgid "What level of permission this user will have"
-msgstr "Vilken nivå av behörighet den här användaren har"
-
-#: extensions/admin/forms/account.py:39
-msgid "Enter the same password as above, for verification."
-msgstr "Ange samma lösenord som ovan för verifiering."
-
-#: extensions/admin/forms/account.py:51
-msgid "Enabled"
-msgstr "Aktiverad"
-
-#: extensions/admin/forms/account.py:116
-msgid "The two password fields didn't match."
-msgstr "Dessa två lösnordsfält matchar inte."
-
-#: extensions/admin/forms/account.py:122
-msgid "You can't disable your own account"
-msgstr "Du kan inte inaktivera ditt eget konto"
-
-#: extensions/admin/forms/account.py:136
-msgid "E-mail"
-msgstr "E-post"
-
-#: extensions/admin/forms/account.py:138 extensions/admin/forms/domain.py:21
-msgid "Quota"
-msgstr "Kvot"
-
-#: extensions/admin/forms/account.py:140
-msgid ""
-"Quota in MB for this mailbox. Define a custom value or use domain's default "
-"one. Leave empty to define an unlimited value (not allowed for domain "
-"administrators)."
-msgstr "Kvot i MB för denna brevlåda. Definiera ett anpassat värde eller använda domänens förvalda. Lämna tomt för att definiera ett obegränsat värde (ej tillåtet för domänadministratörer)."
-
-#: extensions/admin/forms/account.py:148 extensions/admin/forms/domain.py:29
-#: extensions/admin/templates/admin/domains.html:26
-#: extensions/postfix_relay_domains/forms.py:17
-msgid "Alias(es)"
-msgstr "Alias"
-
-#: extensions/admin/forms/account.py:151
-msgid ""
-"Alias(es) of this mailbox. Indicate only one address per input, press ENTER "
-"to add a new input. Use the '*' character to create a 'catchall' alias (ex: "
-"*@domain.tld)."
-msgstr "Alias för denna brevlåda. Ange endast en adress per rad, tryck ENTER för att lägga till ny rad. Använd '*' för att skapa ett 'catchall' alias (ex: *@domain.tld)."
-
-#: extensions/admin/forms/account.py:216 extensions/admin/forms/account.py:246
-#: extensions/admin/forms/alias.py:72
-msgid "Domain does not exist"
-msgstr "Domän existerar inte"
-
-#: extensions/admin/forms/account.py:320
-msgid "Domain(s)"
-msgstr "Domän(er)"
-
-#: extensions/admin/forms/account.py:322
-msgid "Domain(s) that user administrates"
-msgstr "Domän(er) användaren administrerar"
-
-#: extensions/admin/forms/account.py:370 extensions/admin/forms/account.py:446
-msgid "Mail"
-msgstr "Post"
-
-#: extensions/admin/forms/account.py:372
-msgid "Permissions"
-msgstr "Rättigheter"
-
-#: extensions/admin/forms/account.py:434
-msgid "Account updated"
-msgstr "Konto uppdaterat"
-
-#: extensions/admin/forms/account.py:451
-msgid "New account"
-msgstr "Nytt konto"
-
-#: extensions/admin/forms/account.py:463
-msgid "Account created"
-msgstr "Konto skapat"
-
-#: extensions/admin/forms/alias.py:16
-msgid "Email address"
-msgstr "E-post adress"
-
-#: extensions/admin/forms/alias.py:18
-msgid ""
-"The distribution list address. Use the '*' character to create a 'catchall' "
-"address (ex: *@domain.tld)."
-msgstr "Distributionslistans adress. Använd '*' för att skapa en 'catchall' adress (ex: *@domain.tld)."
-
-#: extensions/admin/forms/alias.py:24
-msgid "Recipients"
-msgstr "Mottagare"
-
-#: extensions/admin/forms/alias.py:26
-msgid ""
-"Mailbox(es) this alias will point to. Indicate only one address per input, "
-"press ENTER to add a new input."
-msgstr "Brevlåda/or detta alias kommer att peka på. Ange endast en adress per inlägg, tryck ENTER för att lägga till en ny inlägg."
-
-#: extensions/admin/forms/alias.py:75
-msgid "You don't have access to this domain"
-msgstr "Du har inte åtkomst till denna domän"
-
-#: extensions/admin/forms/alias.py:97
-msgid "Invalid mailbox"
-msgstr "Ogiltig brevlåda"
-
-#: extensions/admin/forms/alias.py:115 extensions/admin/models/alias.py:195
-#, python-format
-msgid "Local recipient %s not found"
-msgstr "Lokal mottagare %s kunde inte hittas"
-
-#: extensions/admin/forms/alias.py:119 extensions/admin/forms/alias.py:127
-#, python-format
-msgid "Recipient %s already present"
-msgstr "Mottagare %s finns redan"
-
-#: extensions/admin/forms/alias.py:133
-msgid "No recipient defined"
-msgstr "Ingen mottagare definierad"
-
-#: extensions/admin/forms/domain.py:24
-msgid ""
-"Default quota in MB applied to mailboxes. Leave empty to use the default "
-"value."
-msgstr "Standard kvota i MB tillämpad på nya brevlådor. Lämna tomt för att använda standardvärdet."
-
-#: extensions/admin/forms/domain.py:32
-msgid ""
-"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
-"add a new input."
-msgstr "Alias för denna domän. Ange endast ett namn per rad, tryck ENTER för att lägga till en rad."
-
-#: extensions/admin/forms/domain.py:87 extensions/admin/forms/domain.py:101
-#: extensions/postfix_relay_domains/forms.py:69
-#: extensions/postfix_relay_domains/forms.py:89
-#, python-format
-msgid "A %s with this name already exists"
-msgstr "En %s med detta namn finns redan"
-
-#: extensions/admin/forms/domain.py:98
-#: extensions/postfix_relay_domains/forms.py:60
-#: extensions/postfix_relay_domains/forms.py:82
-msgid "domain"
-msgstr "domän"
-
-#: extensions/admin/forms/domain.py:182
-msgid "Create a domain administrator"
-msgstr "Skapa en domän administratör"
-
-#: extensions/admin/forms/domain.py:185
-msgid "Automatically create an administrator for this domain"
-msgstr "Skapa en domän administratör automatiskt för denna domän"
-
-#: extensions/admin/forms/domain.py:193
-msgid ""
-"The administrator's name. Don't include the domain's name here, it will be "
-"automatically appended."
-msgstr "Administratörens namn. Inkludera inte domänens namn här, den kommer att läggas till automatiskt."
-
-#: extensions/admin/forms/domain.py:200
-msgid "Create aliases"
-msgstr "Skapa alias."
-
-#: extensions/admin/forms/domain.py:203
-msgid "Automatically create standard aliases for this domain"
-msgstr "Skapa automatiskt standard alias för den här domänen"
-
-#: extensions/admin/forms/domain.py:221
-msgid "Invalid format"
-msgstr "Ogiltigt format"
-
-#: extensions/admin/forms/domain.py:236
-#, python-format
-msgid "User '%s' already exists"
-msgstr "Användare '%s' finns redan"
-
-#: extensions/admin/forms/domain.py:323
-msgid "Domain modified"
-msgstr "Domän ändrad"
-
-#: extensions/admin/forms/domain.py:336
-msgid "Options"
-msgstr "Inställningar"
-
-#: extensions/admin/forms/domain.py:343
-msgid "New domain"
-msgstr "Ny domän"
-
-#: extensions/admin/forms/domain.py:358
-msgid "Domain created"
-msgstr "Domän skapad"
-
-#: extensions/admin/forms/export.py:7
-msgid "File name"
-msgstr "Filnamn"
-
-#: extensions/admin/forms/export.py:13 extensions/admin/forms/import_.py:8
-msgid "Separator"
-msgstr "Separator"
-
-#: extensions/admin/forms/forward.py:12
-msgid "Recipient(s)"
-msgstr "Mottagare"
-
-#: extensions/admin/forms/forward.py:15
-msgid "Indicate one or more recipients separated by a ','"
-msgstr "Ange en eller flera mottagare separerade med ett ','"
-
-#: extensions/admin/forms/forward.py:18
-msgid "Keep local copies"
-msgstr "Behåll lokal kopia"
-
-#: extensions/admin/forms/forward.py:20
-msgid "Forward messages and store copies into your local mailbox"
-msgstr "Vidarebefordra meddelande och spara kopia i din lokala brevlåda"
-
-#: extensions/admin/forms/forward.py:38
-msgid ""
-"You can't define a forward to a local destination. Please ask your "
-"administrator to create an alias instead."
-msgstr "Du kan inte definiera en vidarebefordring till en lokal destination. Be din administratör att skapa ett alias istället."
-
-#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:210
-msgid "Select a file"
-msgstr "Välj en fil"
-
-#: extensions/admin/forms/import_.py:14
-msgid "Continue on error"
-msgstr "Fortsätt vid fel"
-
-#: extensions/admin/forms/import_.py:15
-msgid "Don't treat duplicated objects as error"
-msgstr "Behandla inte dubletter som fel"
-
-#: extensions/admin/forms/import_.py:30
-msgid "Crypt passwords"
-msgstr "Krypterade lösenord"
-
-#: extensions/admin/forms/import_.py:31
-msgid "Check this option if passwords contained in your file are not crypted"
-msgstr "Markera det här alternativet om lösenord i filen inte är krypterad"
-
-#: extensions/admin/models/alias.py:18 extensions/admin/models/mailbox.py:74
-msgid "address"
-msgstr "adress"
-
-#: extensions/admin/models/alias.py:20
-msgid ""
-"The alias address (without the domain part). For a 'catch-all' address, just"
-" enter an * character."
-msgstr "Alias adress (utan domän delen). För en \"catch-all\"-adress, ange bara asterisk *."
-
-#: extensions/admin/models/alias.py:26
-msgid "mailboxes"
-msgstr "brevlådor"
-
-#: extensions/admin/models/alias.py:27
-msgid "The mailboxes this alias points to"
-msgstr "Brevlådorna detta alias pekar till"
-
-#: extensions/admin/models/alias.py:31
-msgid "The aliases this alias points to"
-msgstr "Det alias detta alias pekar till"
-
-#: extensions/admin/models/alias.py:36
-#: extensions/admin/models/domain_alias.py:18
-#: extensions/postfix_relay_domains/models.py:168
-msgid "Check to activate this alias"
-msgstr "Markera för aktivera detta alias"
-
-#: extensions/admin/models/alias.py:81
-msgid "distribution list"
-msgstr "distributionslista"
-
-#: extensions/admin/models/alias.py:82
-msgid "forward"
-msgstr "vidarebefordra"
-
-#: extensions/admin/models/alias.py:83
-msgid "alias"
-msgstr "alias"
-
-#: extensions/admin/models/alias.py:153
-#, python-format
-msgid "Invalid line: %s"
-msgstr "Ogiltig rad: %s"
-
-#: extensions/admin/models/alias.py:158
-#, python-format
-msgid "Domain '%s' does not exist"
-msgstr "Domänen '%s' existerar inte"
-
-#: extensions/admin/models/domain.py:28
-#: extensions/admin/models/domain_alias.py:10
-#: extensions/postfix_relay_domains/models.py:58
-#: extensions/postfix_relay_domains/models.py:76
-#: extensions/postfix_relay_domains/models.py:159
-msgid "name"
-msgstr "namn"
-
-#: extensions/admin/models/domain.py:29
-#: extensions/postfix_relay_domains/models.py:77
-msgid "The domain name"
-msgstr "Domännamnet"
-
-#: extensions/admin/models/domain.py:33
-#: extensions/postfix_relay_domains/models.py:86
-msgid "Check to activate this domain"
-msgstr "Markera för att aktivera denna domän"
-
-#: extensions/admin/models/domain.py:66
-#: extensions/admin/templates/admin/domain_statistics.html:49
-msgid "Domain"
-msgstr "Domän"
-
-#: extensions/admin/models/domain.py:160
-#, python-format
-msgid "Invalid quota value for domain '%s'"
-msgstr "Ogiltig kvota värde för domänen '%s'"
-
-#: extensions/admin/models/domain_alias.py:11
-#: extensions/postfix_relay_domains/models.py:160
-msgid "The alias name"
-msgstr "Alias namn"
-
-#: extensions/admin/models/domain_alias.py:13
-#: extensions/postfix_relay_domains/models.py:163
-msgid "target"
-msgstr "mål"
-
-#: extensions/admin/models/domain_alias.py:14
-msgid "The domain this alias points to"
-msgstr "Domän dit detta alias pekar mot"
-
-#: extensions/admin/models/domain_alias.py:52
-#, python-format
-msgid "Unknown domain %s"
-msgstr "Okänt kommando %s"
-
-#: extensions/admin/models/mailbox.py:75
-msgid "Mailbox address (without the @domain.tld part)"
-msgstr "Brevlåde adress (utan @domain.tld)"
-
-#: extensions/admin/models/mailbox.py:136
-#, python-format
-msgid "Failed to retrieve mailbox location (%s)"
-msgstr "Kunde inte hitta brevlådans sökväg (%s)"
-
-#: extensions/admin/models/mailbox.py:221
-#, python-format
-msgid "Quota is greater than the allowed domain's limit (%dM)"
-msgstr "Kvotan är större än domänens gräns (%dM)"
-
-#: extensions/admin/models/mailbox.py:227
-msgid "A quota is required"
-msgstr "En kvota krävs"
-
-#: extensions/admin/templates/admin/account_general_form.html:9
-#: extensions/admin/templates/admin/aliasform.html:8
-msgid "Domain is disabled"
-msgstr "Domänen är inaktiverad"
-
-#: extensions/admin/templates/admin/domain_general_form.html:3
-#: extensions/admin/templates/admin/mailform.html:3
-#: extensions/admin/templates/admin/newdomainform.html:3
-msgid "MB"
-msgstr "MB"
-
-#: extensions/admin/templates/admin/domain_options_form.html:7
-msgid "You can't create a new domain administrator"
-msgstr "Du kan inte skapa en ny domänadministratör"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-#: extensions/admin/templatetags/admin_tags.py:43
-#: extensions/stats/general_callbacks.py:12
-msgid "Statistics"
-msgstr "Statistik"
-
-#: extensions/admin/templates/admin/domain_statistics.html:15
-msgid "Domains and identities"
-msgstr "Domäner och konton"
-
-#: extensions/admin/templates/admin/domain_statistics.html:22
-msgid "Global counters"
-msgstr "Globala räknare"
-
-#: extensions/admin/templates/admin/domain_statistics.html:26
-msgid "Type"
-msgstr "Typ"
-
-#: extensions/admin/templates/admin/domain_statistics.html:27
-msgid "Quantity"
-msgstr "Mängd"
-
-#: extensions/admin/templates/admin/domain_statistics.html:33
-#: extensions/admin/templates/admin/editdomainform.html:24
-#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20
-msgid "Domain aliases"
-msgstr "Domän alias"
-
-#: extensions/admin/templates/admin/domain_statistics.html:45
-msgid "Per-domain counters"
-msgstr "Per domän räknare"
-
-#: extensions/admin/templates/admin/domains.html:27
-#: extensions/admin/templates/admin/identity_headers.html:4
-#: extensions/radicale/templates/radicale/calendars.html:50
-msgid "Tags"
-msgstr "Tagg"
-
-#: extensions/admin/templates/admin/domains.html:28
-#: extensions/admin/templates/admin/identity_headers.html:5
-#: extensions/radicale/templates/radicale/calendars.html:51
-#: extensions/sievefilters/views.py:95
-#: extensions/sievefilters/templates/sievefilters/filter.html:20
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:5
-#: extensions/webmail/templatetags/webmail_tags.py:98
-msgid "Actions"
-msgstr "Åtgärder"
-
-#: extensions/admin/templates/admin/domains_table.html:4
-msgid "disabled"
-msgstr "inaktiverad"
-
-#: extensions/admin/templates/admin/editdomainform.html:4
-msgid "Administrators"
-msgstr "Administratörer"
-
-#: extensions/admin/templates/admin/editdomainform.html:19
-msgid "No domain administrator defined"
-msgstr "Ingen domän administratör definierad"
-
-#: extensions/admin/templates/admin/editdomainform.html:22
-msgid "Creation date"
-msgstr "Skapelsedatum"
-
-#: extensions/admin/templates/admin/editdomainform.html:23
-msgid "Last modification date"
-msgstr "Senast ändrad"
-
-#: extensions/admin/templates/admin/editdomainform.html:26
-#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25
-msgid "Mailbox aliases"
-msgstr "Brevlåde alias"
-
-#: extensions/admin/templates/admin/forward.html:2
-msgid "Automatically forward emails to another address"
-msgstr "Vidarebefordra automatiskt e-post till en annan adress"
-
-#: extensions/admin/templates/admin/identity_headers.html:3
-msgid "Fullname/Recipient"
-msgstr "Fullständigt namn/Mottagare"
-
-#: extensions/admin/templates/admin/importform.html:6
-msgid "Help"
-msgstr "Hjälp"
-
-#: extensions/admin/templates/admin/importform.html:13
-msgid "Importing..."
-msgstr "Importerar..."
-
-#: extensions/admin/templates/admin/mailboxes_raw.html:3
-msgid "Choose a value"
-msgstr "Välj ett värde"
-
-#: extensions/admin/templates/admin/mailform.html:3
-msgid "Use domain default value"
-msgstr "Använd domänens standardvärde"
-
-#: extensions/admin/templates/admin/quota_headers.html:2
-msgid "Address"
-msgstr "Adress"
-
-#: extensions/admin/templates/admin/quota_headers.html:3
-msgid "Value"
-msgstr "Värde"
-
-#: extensions/admin/templates/admin/quota_headers.html:4
-msgid "Limit"
-msgstr "Gräns"
-
-#: extensions/admin/templates/admin/quota_headers.html:5
-#, python-format
-msgid "Usage (%%)"
-msgstr "Användning (%%)"
-
-#: extensions/admin/templates/admin/searchform.html:6
-msgid "Search"
-msgstr "Sök"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_m"
-msgstr "enabled_m"
-
-#: extensions/admin/templatetags/admin_tags.py:17
-msgid "enabled_f"
-msgstr "enabled_f"
-
-#: extensions/admin/templatetags/admin_tags.py:38
-msgid "List domains"
-msgstr "Lista domäner"
-
-#: extensions/admin/templatetags/admin_tags.py:51
-msgid "Add domain"
-msgstr "Lägg till domän"
-
-#: extensions/admin/templatetags/admin_tags.py:60
-#: extensions/admin/templatetags/admin_tags.py:124
-#: extensions/admin/views/import.py:48 extensions/admin/views/import.py:162
-msgid "Import"
-msgstr "Importera"
-
-#: extensions/admin/templatetags/admin_tags.py:66
-#: extensions/admin/templatetags/admin_tags.py:130
-#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64
-msgid "Export"
-msgstr "Exportera"
-
-#: extensions/admin/templatetags/admin_tags.py:90
-msgid "List identities"
-msgstr "Lista konton"
-
-#: extensions/admin/templatetags/admin_tags.py:95
-msgid "List quotas"
-msgstr "Lista kvoter"
-
-#: extensions/admin/templatetags/admin_tags.py:100
-msgid "Add account"
-msgstr "Lägg till konto"
-
-#: extensions/admin/templatetags/admin_tags.py:106
-msgid "Add alias"
-msgstr "Lägg till alias"
-
-#: extensions/admin/templatetags/admin_tags.py:112
-msgid "Add forward"
-msgstr "Lägg till vidarebefodring"
-
-#: extensions/admin/templatetags/admin_tags.py:118
-msgid "Add distribution list"
-msgstr "Lägg till distributionslista"
-
-#: extensions/admin/templatetags/admin_tags.py:151
-msgid "View the domain's identities"
-msgstr "Visa domänens konton"
-
-#: extensions/admin/templatetags/admin_tags.py:158
-#: extensions/admin/templatetags/admin_tags.py:177
-#: extensions/admin/templatetags/admin_tags.py:184
-#: extensions/postfix_relay_domains/general_callbacks.py:84
-#: extensions/radicale/templatetags/radicale_tags.py:72
-#, python-format
-msgid "Delete %s?"
-msgstr "Radera %s?"
-
-#: extensions/admin/templatetags/admin_tags.py:260
-msgid "Remove this permission"
-msgstr "Radera detta tillstånd"
-
-#: extensions/admin/views/alias.py:26
-msgid "Alias with this name already exists"
-msgstr "Alias med detta namn existerar redan"
-
-#: extensions/admin/views/alias.py:50
-#: extensions/postfix_relay_domains/views.py:34
-#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233
-#: extensions/webmail/views.py:167
-msgid "Create"
-msgstr "Skapa"
-
-#: extensions/admin/views/alias.py:62
-msgid "New distribution list"
-msgstr "Ny distributionslista"
-
-#: extensions/admin/views/alias.py:63
-msgid "Distribution list created"
-msgstr "Distributionslista skapad"
-
-#: extensions/admin/views/alias.py:72
-msgid "New alias"
-msgstr "Nytt alias"
-
-#: extensions/admin/views/alias.py:73
-msgid "Alias created"
-msgstr "Alias skapat"
-
-#: extensions/admin/views/alias.py:82
-msgid "New forward"
-msgstr "Ny vidarebefodring"
-
-#: extensions/admin/views/alias.py:83
-msgid "Forward created"
-msgstr "Vidarebefodring skapad"
-
-#: extensions/admin/views/alias.py:96
-msgid "Distribution list modified"
-msgstr "Distributionslista ändrad"
-
-#: extensions/admin/views/alias.py:98
-msgid "Forward modified"
-msgstr "Vidarebefodring ändrad"
-
-#: extensions/admin/views/alias.py:100
-msgid "Alias modified"
-msgstr "Alias ändrat"
-
-#: extensions/admin/views/domain.py:135
-msgid "You can't delete your own domain"
-msgstr "Du kan inte radera din egen domän"
-
-#: extensions/admin/views/domain.py:138
-msgid "Domain deleted"
-msgid_plural "Domains deleted"
-msgstr[0] "Domän raderad"
-msgstr[1] "Domäner raderade"
-
-#: extensions/admin/views/export.py:37
-msgid "Export identities"
-msgstr "Exportera konton"
-
-#: extensions/admin/views/export.py:63
-msgid "Export domains"
-msgstr "Exportera domäner"
-
-#: extensions/admin/views/identity.py:95
-#: extensions/admin/views/identity.py:193
-#: extensions/admin/views/identity.py:198 extensions/amavis/views.py:222
-#: extensions/amavis/views.py:226 extensions/amavis/views.py:257
-#: extensions/amavis/views.py:262 extensions/amavis/views.py:264
-#: extensions/webmail/views.py:57 extensions/webmail/views.py:75
-#: extensions/webmail/views.py:89 extensions/webmail/views.py:107
-#: extensions/webmail/views.py:126 extensions/webmail/views.py:140
-#: extensions/webmail/views.py:216 extensions/webmail/views.py:239
-#: extensions/webmail/views.py:435 extensions/webmail/views.py:485
-#: extensions/webmail/views.py:501 extensions/webmail/views.py:534
-#: extensions/webmail/views.py:574 lib/formutils.py:118 lib/formutils.py:121
-msgid "Invalid request"
-msgstr "Ogiltig förfrågan"
-
-#: extensions/admin/views/identity.py:183
-msgid "Account deleted"
-msgid_plural "Accounts deleted"
-msgstr[0] "Konto raderat"
-msgstr[1] "Konton raderade"
-
-#: extensions/admin/views/import.py:36
-#, python-format
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
+" the "
+"mailing list .\n"
+msgstr ""
+"\n"
+"Välkommen till online-demot! \n"
+"Varning: demots innehåll återställs varannan timme
\n"
+"För att prova demot, följande användare finns tillgängliga "
+"(användarnamn/lösenord ):
\n"
"\n"
-" domain; name; quota; enabled \n"
-" domainalias; name; targeted domain; enabled \n"
-" %s\n"
+"En super administratör: admin/password \n"
+"En domän administratölr: admin@demo.local/admin \n"
+"En enkel användare: user@demo.local/user \n"
" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"You can use a different character as separator.
\n"
-msgstr "Tillhandahåll en CSV fil där raderna har följande format:\n\ndomain; name; quota; enabled \ndomainalias; name; targeted domain; enabled \n%s\n \ndet första elementet i varje rad är obligatoriskt och måste vara lika med en av de tidigare värdena. p>\n
Du kan använda ett annat tecken som separator. p>\n"
-
-#: extensions/admin/views/import.py:47
-msgid "Import domains"
-msgstr "Importera domäner"
-
-#: extensions/admin/views/import.py:125
-#, python-format
-msgid "Object already exists: %s"
-msgstr "Objektet existerar redan: %s"
-
-#: extensions/admin/views/import.py:129
-#, python-format
-msgid "%d objects imported successfully"
-msgstr "%d objekt importerade"
-
-#: extensions/admin/views/import.py:149
-msgid ""
-"Provide a CSV file where lines respect one of the following formats:\n"
-"
\n"
-"account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...] \n"
-"alias; address; enabled; internal recipient \n"
-"forward; address; enabled; external recipient \n"
-"dlist; address; enabled; recipient; recipient; ... \n"
-" \n"
-"The first element of each line is mandatory and must be equal to one of the previous values.
\n"
-"\n"
-"You can use a different character as separator.
\n"
-msgstr "Tillhandahåll en CSV-fil där raderna har följande format:\n\naccount; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...] \nalias; address; enabled; internal recipient \nforward; address; enabled; external recipient \ndlist; address; enabled; recipient; recipient; ... \n \nDet första elementet i varje rad är obligatorisk och måste vara lika med en av de tidigare värdena.
\n\nDu kan använda ett annat tecken separator.
\n"
-
-#: extensions/admin/views/import.py:161
-msgid "Import identities"
-msgstr "Importera konton"
-
-#: extensions/admin/views/user.py:38
-msgid "Forward updated"
-msgstr "Vidarebefordring uppdaterad"
-
-#: extensions/amavis/__init__.py:21
-msgid "Simple amavis management frontend"
-msgstr "Enkel amavis hantering frontend"
-
-#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:20
-msgid "Quarantine"
-msgstr "Karantän"
-
-#: extensions/amavis/app_settings.py:16
-msgid "Quarantine settings"
-msgstr "Karantän inställningar"
-
-#: extensions/amavis/app_settings.py:19
-msgid "Maximum message age"
-msgstr "Maximal meddelandeålder"
-
-#: extensions/amavis/app_settings.py:22
-msgid "Quarantine messages maximum age (in days) before deletion"
-msgstr "Maximalt antal dagar meddelanden behålls i karantän innan radering"
-
-#: extensions/amavis/app_settings.py:26
-msgid "Messages releasing"
-msgstr "Meddelanden frisläppta"
-
-#: extensions/amavis/app_settings.py:29
-msgid "Remove released messages"
-msgstr "Radera frisläppta meddelanden"
-
-#: extensions/amavis/app_settings.py:31
-msgid "Remove messages marked as released while cleaning up the database"
-msgstr "Ta bort meddelanden markerade som släppta när vi städar databasen"
-
-#: extensions/amavis/app_settings.py:36
-msgid "Amavis connection mode"
-msgstr "Amavis anslutningsläge"
-
-#: extensions/amavis/app_settings.py:39
-msgid "Mode used to access the PDP server"
-msgstr "Läge som används för att komma åt PDP-servern"
-
-#: extensions/amavis/app_settings.py:44
-msgid "PDP server address"
-msgstr "PDP server adress"
-
-#: extensions/amavis/app_settings.py:46
-msgid "PDP server address (if inet mode)"
-msgstr "PDP-server adress (om inet läge)"
-
-#: extensions/amavis/app_settings.py:51
-msgid "PDP server port"
-msgstr "PDP server port"
-
-#: extensions/amavis/app_settings.py:53
-msgid "PDP server port (if inet mode)"
-msgstr "PDP serverport (om inet läge)"
-
-#: extensions/amavis/app_settings.py:57
-msgid "PDP server socket"
-msgstr "PDP server socket"
-
-#: extensions/amavis/app_settings.py:59
-msgid "Path to the PDP server socket (if unix mode)"
-msgstr "Sökväg till PDP-servern uttaget (om Unix-läge)"
-
-#: extensions/amavis/app_settings.py:63
-msgid "Allow direct release"
-msgstr "Möjliggör direkt frisläpp"
-
-#: extensions/amavis/app_settings.py:65
-msgid "Allow users to directly release their messages"
-msgstr "Tillåt användare att frisläppa sina meddelanden"
-
-#: extensions/amavis/app_settings.py:69
-msgid "Enable self-service mode"
-msgstr "Aktivera \"själv-service\" läge"
-
-#: extensions/amavis/app_settings.py:71
-msgid "Activate the 'self-service' mode"
-msgstr "Aktivera \"själv-service\" läge"
-
-#: extensions/amavis/app_settings.py:75
-msgid "Notifications sender"
-msgstr "Notifierings avsändare"
-
-#: extensions/amavis/app_settings.py:77
-msgid "The e-mail address used to send notitications"
-msgstr "E-postadress att använda för att skicka notifikationer"
-
-#: extensions/amavis/app_settings.py:80
-#: extensions/amavis/templates/amavis/main_action_bar.html:31
-msgid "Manual learning"
-msgstr "Manuell inlärning"
-
-#: extensions/amavis/app_settings.py:83
-msgid "Enable manual learning"
-msgstr "Aktivera manuell inlärning"
-
-#: extensions/amavis/app_settings.py:86
-msgid "Allow super administrators to manually train Spamassassin"
-msgstr "Tillåt super administratörer att manuellt träna Spamassassin"
-
-#: extensions/amavis/app_settings.py:91
-msgid "Is Spamassassin local?"
-msgstr "Är Spamassasin lokal?"
-
-#: extensions/amavis/app_settings.py:94
-msgid "Tell if Spamassassin is running on the same server than modoboa"
-msgstr "Ange om Spamassassin körs på samma server som modoboa"
-
-#: extensions/amavis/app_settings.py:99
-msgid "Default user"
-msgstr "Standardanvändare"
-
-#: extensions/amavis/app_settings.py:102
-msgid "Name of the user owning the default bayesian database"
-msgstr "Namn på den användare som äger standard bayesian databasen"
-
-#: extensions/amavis/app_settings.py:107
-msgid "Spamd address"
-msgstr "Spamd adress"
-
-#: extensions/amavis/app_settings.py:109
-msgid "The IP address where spamd can be reached"
-msgstr "IP-adress där spamd kan nås"
-
-#: extensions/amavis/app_settings.py:113
-msgid "Spamd port"
-msgstr "Spamd port"
-
-#: extensions/amavis/app_settings.py:115
-msgid "The TCP port spamd is listening on"
-msgstr "TCP porten spamd lyssnar på"
-
-#: extensions/amavis/app_settings.py:119
-msgid "Enable per-domain manual learning"
-msgstr "Aktivera per-domän manuell inlärning"
-
-#: extensions/amavis/app_settings.py:122
-msgid ""
-"Allow domain administrators to train Spamassassin (within dedicated per-"
-"domain databases)"
-msgstr "Tillåt domänadministratörer att träna Spamassassin (inom dedikerade per-domän databaser)"
-
-#: extensions/amavis/app_settings.py:128
-msgid "Enable per-user manual learning"
-msgstr "Aktivera per-användare manuell inlärning"
-
-#: extensions/amavis/app_settings.py:131
-msgid ""
-"Allow simple users to personally train Spamassassin (within a dedicated "
-"database)"
-msgstr "Tillåt enkla användare att personligen träna Spamassassin (inom en dedikerad databas)"
-
-#: extensions/amavis/app_settings.py:160 extensions/webmail/app_settings.py:91
-msgid "Number of displayed emails per page"
-msgstr "Antalet visade e-postmeddelanden per sida"
-
-#: extensions/amavis/app_settings.py:161
-msgid "Set the maximum number of messages displayed in a page"
-msgstr "Anger det maximala antalet meddelanden som visas på en sida"
-
-#: extensions/amavis/forms.py:88
-msgid "Global database"
-msgstr "Global databas"
-
-#: extensions/amavis/forms.py:94
-msgid "Domain's database"
-msgstr "Domänens databas"
-
-#: extensions/amavis/forms.py:96
-msgid "User's database"
-msgstr "Användarens databas"
-
-#: extensions/amavis/general_callbacks.py:149
-msgid "Pending requests"
-msgstr "Väntande förfrågningar"
-
-#: extensions/amavis/general_callbacks.py:159
-msgid "Content filter"
-msgstr "Innehålls filter"
-
-#: extensions/amavis/lib.py:62
-#, python-format
-msgid "Connection to amavis failed: %s"
-msgstr "Anslutning till amavis misslyckades: %s"
-
-#: extensions/amavis/lib.py:131
-msgid "No recipient found"
-msgstr "Inga mottagare hittade"
-
-#: extensions/amavis/models.py:93
-msgid "Virus filter"
-msgstr "Virus filter"
-
-#: extensions/amavis/models.py:94 extensions/amavis/models.py:102
-#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293
-msgid "yes"
-msgstr "ja"
-
-#: extensions/amavis/models.py:95 extensions/amavis/models.py:103
-#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297
-msgid "no"
-msgstr "nej"
-
-#: extensions/amavis/models.py:96 extensions/amavis/models.py:104
-#: extensions/amavis/models.py:112
-#: extensions/amavis/templates/amavis/domain_content_filter.html:17
-msgid "default"
-msgstr "standard"
-
-#: extensions/amavis/models.py:98
-msgid "Bypass virus checks or not. Choose 'default' to use global settings."
-msgstr "Kringgå virus kontroller eller ej. Välj \"standard\" för att använda globala inställningar."
-
-#: extensions/amavis/models.py:101
-msgid "Spam filter"
-msgstr "Skräp filter"
-
-#: extensions/amavis/models.py:106
-msgid "Bypass spam checks or not. Choose 'default' to use global settings."
-msgstr "Kringgå skräp filter eller ej. Välj 'standard' för att använda globala inställningar."
-
-#: extensions/amavis/models.py:109
-msgid "Banned filter"
-msgstr "Förbjudna filter"
-
-#: extensions/amavis/models.py:114
-msgid "Bypass banned checks or not. Choose 'default' to use global settings."
-msgstr "Kringgå förbjudna filter eller inte. Välj 'standard' för att använda globala inställningar."
-
-#: extensions/amavis/models.py:144
-msgid "Spam marker"
-msgstr "Skräp markering"
-
-#: extensions/amavis/models.py:146
-msgid ""
-"Modify spam subject using the specified text. Choose 'default' to use global"
-" settings."
-msgstr "Ändra skräppost ämnesrad med vald text. Välj 'standard' för att använd globala inställningar."
-
-#: extensions/amavis/views.py:38
-msgid "Empty quarantine"
-msgstr "Karantän tom"
-
-#: extensions/amavis/views.py:227
-msgid "Message deleted"
-msgstr "Meddelande raderat"
-
-#: extensions/amavis/views.py:244
-#, python-format
-msgid "%(count)d message deleted successfully"
-msgid_plural "%(count)d messages deleted successfully"
-msgstr[0] "%(count)d meddelande raderadat"
-msgstr[1] "%(count)d meddelanden raderade"
-
-#: extensions/amavis/views.py:267
-msgid "Request sent"
-msgstr "Begäran skickad"
-
-#: extensions/amavis/views.py:273
-msgid "Message released"
-msgstr "Meddelande släppt"
-
-#: extensions/amavis/views.py:300
-#, python-format
-msgid "%(count)d request sent"
-msgid_plural "%(count)d requests sent"
-msgstr[0] "%(count)d förfrågning skickad"
-msgstr[1] "%(count)d förfrågningar skickadade"
-
-#: extensions/amavis/views.py:321
-#, python-format
-msgid "%(count)d message released successfully"
-msgid_plural "%(count)d messages released successfully"
-msgstr[0] "%(count)d meddelande frisläppt"
-msgstr[1] "%(count)d meddelanden frisläppta"
-
-#: extensions/amavis/views.py:360
-#, python-format
-msgid "%(count)d message processed successfully"
-msgid_plural "%(count)d messages processed successfully"
-msgstr[0] "%(count)d meddelande framgångsrikt behandlat"
-msgstr[1] "%(count)d meddelanden framgångsrikt behandlade"
-
-#: extensions/amavis/views.py:394
-msgid "Select a database"
-msgstr "Välj databas"
-
-#: extensions/amavis/views.py:398
-msgid "Validate"
-msgstr "Validera"
-
-#: extensions/amavis/management/commands/amnotify.py:61
-msgid "[modoboa] Pending release requests"
-msgstr "[modoboa] Väntande release förfrågningar"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:5
-msgid "Thresholds"
-msgstr "Trösklar"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:9
-msgid "or more is spam"
-msgstr "eller mera skräppost"
-
-#: extensions/amavis/templates/amavis/domain_content_filter.html:15
-msgid "or more throw spam message away"
-msgstr "eller mera kasta skräp meddelande"
-
-#: extensions/amavis/templates/amavis/email_list.html:11
-msgid "Score"
-msgstr "Poäng"
-
-#: extensions/amavis/templates/amavis/email_list.html:14
-#: extensions/amavis/templatetags/amavis_tags.py:111
-#: extensions/webmail/forms.py:83
-#: extensions/webmail/templates/webmail/compose.html:9
-msgid "To"
-msgstr "Till"
-
-#: extensions/amavis/templates/amavis/email_list.html:17
-#: extensions/postfix_autoreply/forms.py:10
-msgid "From"
-msgstr "Från"
-
-#: extensions/amavis/templates/amavis/email_list.html:20
-#: extensions/sievefilters/forms.py:83 extensions/webmail/forms.py:87
-#: extensions/webmail/lib/imapemail.py:298
-#: templates/common/email_searchbar.html:17
-msgid "Subject"
-msgstr "Ämne"
-
-#: extensions/amavis/templates/amavis/emails_page.html:15
-msgid "Released"
-msgstr "Släppt"
-
-#: extensions/amavis/templates/amavis/emails_page.html:17
-msgid "Marked as spam"
-msgstr "Markerad som spam"
-
-#: extensions/amavis/templates/amavis/emails_page.html:19
-msgid "Marked as non-spam"
-msgstr "Markerad som icke spam"
-
-#: extensions/amavis/templates/amavis/index.html:4
-msgid "Quarantine management"
-msgstr "Hantera karantän"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:5
-msgid "Select"
-msgstr "Välj"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:11
-msgid "Clean"
-msgstr "Ren"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:12
-msgid "Spam"
-msgstr "Skräp"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:13
-msgid "Virus"
-msgstr "Virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:14
-msgid "Bad Header"
-msgstr "Dålig rubrik"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:15
-msgid "Bad MIME"
-msgstr "Dålig MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:16
-msgid "Banned"
-msgstr "Förbjuden"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:20
-#: extensions/amavis/templates/amavis/main_action_bar.html:22
-#: extensions/amavis/templatetags/amavis_tags.py:30
-#: extensions/amavis/templatetags/amavis_tags.py:90
-msgid "Release"
-msgstr "Släpp"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:25
-#: extensions/amavis/templates/amavis/main_action_bar.html:27
-#: extensions/amavis/templatetags/amavis_tags.py:36
-#: extensions/amavis/templatetags/amavis_tags.py:97
-#: extensions/webmail/templatetags/webmail_tags.py:45
-#: extensions/webmail/templatetags/webmail_tags.py:92
-msgid "Delete"
-msgstr "Radera"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:36
-#: extensions/amavis/templatetags/amavis_tags.py:49
-msgid "Mark as spam"
-msgstr "Markera som spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:37
-#: extensions/amavis/templatetags/amavis_tags.py:57
-msgid "Mark as non-spam"
-msgstr "Markera som icke spam"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-#: extensions/sievefilters/forms.py:70
-msgid "All messages"
-msgstr "Alla meddelanden"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:54
-msgid "All"
-msgstr "Alla"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:57
-msgid "Clean only"
-msgstr "Enbart rena"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:60
-msgid "Spam only"
-msgstr "Bara skräp"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:63
-msgid "Virus only"
-msgstr "Bara virus"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:66
-msgid "Bad Header only"
-msgstr "Bara dåliga rubriker"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:69
-msgid "Bad MIME only"
-msgstr "Bara dålig MIME"
-
-#: extensions/amavis/templates/amavis/main_action_bar.html:72
-msgid "Banned only"
-msgstr "Bara förbjudna"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:1
-#, python-format
-msgid ""
-"\n"
-"%(counter)s release request is pending for action.\n"
-msgid_plural ""
-"\n"
-"%(counter)s release requests are pending for action.\n"
-msgstr[0] "\n%(counter)s frisläpps förfrågning väntar på åtgärd.\n"
-msgstr[1] "\n%(counter)s frisläpps förfrågningar väntar på åtgärd.'\n"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:6
-msgid "Sketch:"
-msgstr "Sketch:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:8
-msgid "From:"
-msgstr "Från:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:9
-msgid "To:"
-msgstr "Till:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:10
-msgid "Date:"
-msgstr "Datum:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:11
-msgid "Subject:"
-msgstr "Ämne:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:12
-msgid "Act on this message:"
-msgstr "Agera på detta meddelande:"
-
-#: extensions/amavis/templates/amavis/notifications/pending_requests.html:14
-#, python-format
-msgid "Please visit %(listingurl)s for a full listing."
-msgstr "Besök %(listingurl)s för full lista."
-
-#: extensions/amavis/templatetags/amavis_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:24
-#: extensions/webmail/templatetags/webmail_tags.py:73
-msgid "Back"
-msgstr "Tillbaka"
-
-#: extensions/amavis/templatetags/amavis_tags.py:40
-msgid "View full headers"
-msgstr "Visa meddelandehuvuden"
-
-#: extensions/limits/__init__.py:26
-msgid ""
-"Per administrator resources to limit the number of objects they can create"
-msgstr "Per administratör resurser för att begränsa antalet objekt som de kan skapa"
-
-#: extensions/limits/__init__.py:59
-msgid "Limits"
-msgstr "Gräns"
-
-#: extensions/limits/app_settings.py:10
-msgid "Default limits"
-msgstr "Standard gränser"
-
-#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14
-msgid "Domain admins"
-msgstr "Domänadministratörer"
-
-#: extensions/limits/app_settings.py:15
-msgid ""
-"Maximum number of allowed domain administrators for a new administrator"
-msgstr "Maximalt antal domänadministratörer den här användaren kan skapa"
-
-#: extensions/limits/app_settings.py:21
-msgid "Maximum number of allowed domains for a new administrator"
-msgstr "Maximalt antal domäner för en ny administratör"
-
-#: extensions/limits/app_settings.py:27
-msgid "Maximum number of allowed domain aliases for a new administrator"
-msgstr "Maximalt antal domän alias för en ny administratör"
-
-#: extensions/limits/app_settings.py:33
-msgid "Maximum number of allowed mailboxes for a new administrator"
-msgstr "Maximalt antal tillåtna brevlådor för en ny administratör"
-
-#: extensions/limits/app_settings.py:39
-msgid "Maximum number of allowed aliases for a new administrator"
-msgstr "Maximalt antal tillåtna alias för en ny administratör"
-
-#: extensions/limits/forms.py:28 extensions/limits/forms.py:35
-msgid "Invalid limit"
-msgstr "Ogiltig gräns"
-
-#: extensions/limits/forms.py:57
-msgid "Your resources are not initialized yet"
-msgstr "Dina resurser har ännu inte initierats"
-
-#: extensions/limits/forms.py:61
-msgid "You're not allowed to define unlimited values"
-msgstr "Du har inte tillåtelse att definiera obegränsat värden"
-
-#: extensions/limits/general_callbacks.py:10
-msgid "Reseller"
-msgstr "Återförsäljare"
-
-#: extensions/limits/general_callbacks.py:48
-msgid "Resources"
-msgstr "Resurser"
-
-#: extensions/limits/lib.py:19
-#, python-format
-msgid "%s: limit reached"
-msgstr "%s: gräns uppnådd"
-
-#: extensions/limits/lib.py:29
-msgid "Not enough resources"
-msgstr "Inte tillräckligt med resurser"
-
-#: extensions/limits/models.py:15
-msgid "Maximum number of domain administrators this user can create"
-msgstr "Maximalt antal domänadministratörer den här användaren kan skapa"
-
-#: extensions/limits/models.py:18
-msgid "Maximum number of domains this user can create"
-msgstr "Maximalt antal domäner den här användaren kan skapa"
-
-#: extensions/limits/models.py:21
-msgid "Maximum number of domain aliases this user can create"
-msgstr "Maximalt antal domänen alias den här användaren kan skapa"
-
-#: extensions/limits/models.py:24
-msgid "Maximum number of mailboxes this user can create"
-msgstr "Maximalt antal brevlådor den här användaren kan skapa"
-
-#: extensions/limits/models.py:26
-msgid "Maximum number of mailbox aliases this user can create"
-msgstr "Maximalt antal brevlådealias den här användaren kan skapa"
-
-#: extensions/limits/models.py:136
-msgid "undefined"
-msgstr "odefinierad"
-
-#: extensions/limits/models.py:138
-msgid "unlimited"
-msgstr "obegränsad"
-
-#: extensions/limits/templates/limits/poolusage.html:3
-msgid "Resources usage"
-msgstr "Resurs användande"
-
-#: extensions/postfix_autoreply/__init__.py:26
-msgid "Auto-reply (vacation) functionality using Postfix"
-msgstr "Automatiskt svar (semester) funktionalitet med Postfix"
-
-#: extensions/postfix_autoreply/__init__.py:49
-msgid "Automatic replies"
-msgstr "Automatiska svar"
-
-#: extensions/postfix_autoreply/app_settings.py:14
-msgid "Automatic reply timeout"
-msgstr "Automatiskt svar timeout"
-
-#: extensions/postfix_autoreply/app_settings.py:16
-msgid "Timeout in seconds between two auto-replies to the same recipient"
-msgstr "Timeout i sekunder mellan två auto-svar till samma mottagare"
-
-#: extensions/postfix_autoreply/app_settings.py:21
-msgid "Default subject"
-msgstr "Standard ämne"
-
-#: extensions/postfix_autoreply/app_settings.py:22
-msgid "I'm off"
-msgstr "Jag är borta"
-
-#: extensions/postfix_autoreply/app_settings.py:24
-msgid ""
-"Default subject used when an auto-reply message is created automatically"
-msgstr "Standard ämne när ett autosvarsmeddelande skapas automatiskt."
-
-#: extensions/postfix_autoreply/app_settings.py:30
-msgid "Default content"
-msgstr "Standard innehålle"
-
-#: extensions/postfix_autoreply/app_settings.py:32
-#, python-format
-msgid ""
-"I'm currently off. I'll answer as soon as I come back.\n"
-"\n"
-"Best regards,\n"
-"%(name)s\n"
-msgstr "Jag är borta. Jag svarar så fort jag kommer tillbaka.\n\nMed vänliga hälsningar,\n%(name)s\n"
-
-#: extensions/postfix_autoreply/app_settings.py:38
-#, python-format
-msgid ""
-"Default content used when an auto-reply message is created automatically. "
-"The '%(name)s' macro will be replaced by the user's full name."
-msgstr "Standard innehåll som används när ett autosvarsmeddelande skapas automatiskt. '%(name)s' ersätts med användarens fullständiga namn."
-
-#: extensions/postfix_autoreply/forms.py:12
-msgid "Activate your auto reply from this date"
-msgstr "Aktivera ditt autosvar från och med detta datum"
-
-#: extensions/postfix_autoreply/forms.py:18
-msgid "Until"
-msgstr "Tills"
-
-#: extensions/postfix_autoreply/forms.py:20
-msgid "Activate your auto reply until this date"
-msgstr "Aktivera auto-svar fram till detta datum"
-
-#: extensions/postfix_autoreply/forms.py:65
-#: extensions/postfix_autoreply/forms.py:72
-msgid "This date is over"
-msgstr "Detta datum har varit"
-
-#: extensions/postfix_autoreply/forms.py:77
-msgid "Must be greater than start date"
-msgstr "Måste vara större än startdatum"
-
-#: extensions/postfix_autoreply/general_callbacks.py:30
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Auto-reply message"
-msgstr "Auto-svar meddelande"
-
-#: extensions/postfix_autoreply/general_callbacks.py:115
-msgid "Enable auto-reply"
-msgstr "Aktivera autosvar"
-
-#: extensions/postfix_autoreply/general_callbacks.py:117
-msgid "Enable or disable Postfix auto-reply"
-msgstr "Aktivera eller avaktivera Postfix autosvar"
-
-#: extensions/postfix_autoreply/models.py:20
-msgid "subject"
-msgstr "ämne"
-
-#: extensions/postfix_autoreply/models.py:21
-msgid "The subject that will appear in sent emails"
-msgstr "Ämnesraden i skickade e-post meddelanden"
-
-#: extensions/postfix_autoreply/models.py:24
-msgid "content"
-msgstr "innehåll"
-
-#: extensions/postfix_autoreply/models.py:25
-msgid "The content that will appear in sent emails"
-msgstr "Innehållet i skickade e-post meddelanden"
-
-#: extensions/postfix_autoreply/models.py:29
-msgid "Activate/Deactivate your auto reply"
-msgstr "Aktivera / inaktivera din autosvar"
-
-#: extensions/postfix_autoreply/views.py:34
-msgid "Auto reply message updated successfully."
-msgstr "Automatisk svarsmeddelande uppdaterats."
-
-#: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2
-msgid "Define a message to automatically send when you are off"
-msgstr "Skriv meddelande att skicka automatiskt när du är borta"
-
-#: extensions/postfix_relay_domains/__init__.py:72
-msgid "Relay domains support for Postfix"
-msgstr "Relay domän support för Postfix"
-
-#: extensions/postfix_relay_domains/__init__.py:89
-#: extensions/postfix_relay_domains/general_callbacks.py:100
-#: extensions/postfix_relay_domains/limits_callbacks.py:16
-msgid "Relay domains"
-msgstr "Relay domän"
-
-#: extensions/postfix_relay_domains/app_settings.py:21
-msgid "Postfix's master.cf path"
-msgstr "Sökväg till Postfix master.cf"
-
-#: extensions/postfix_relay_domains/app_settings.py:23
-msgid "Path to the master.cf configuration file"
-msgstr "Sökväg till master.cf konfigureringsfil"
-
-#: extensions/postfix_relay_domains/forms.py:20
-msgid ""
-"Alias(es) of this relay domain. Indicate only one name per input, press "
-"ENTER to add a new input."
-msgstr "Alias för den här relay domänen. Ange bara ett namn per rad, tryck ENTER för att lägga till en ny rad."
-
-#: extensions/postfix_relay_domains/forms.py:62
-#: extensions/postfix_relay_domains/general_callbacks.py:93
-msgid "relay domain alias"
-msgstr "relay domän alias"
-
-#: extensions/postfix_relay_domains/forms.py:80
-#: extensions/postfix_relay_domains/general_callbacks.py:92
-msgid "relay domain"
-msgstr "relay domän"
-
-#: extensions/postfix_relay_domains/forms.py:186
-msgid "Relay domain modified"
-msgstr "Relay domän ändrad"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:35
-msgid "Add relay domain"
-msgstr "Lägg till relay domän"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:101
-msgid "Maximum number of relay domains this user can create"
-msgstr "Max antal relay domäner den här användaren kan skapa"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:103
-#: extensions/postfix_relay_domains/limits_callbacks.py:24
-msgid "Relay domain aliases"
-msgstr "Relay domän alias"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:104
-msgid "Maximum number of relay domain aliases this user can create"
-msgstr "Max antal relay domän alias den här användaren kan skapa"
-
-#: extensions/postfix_relay_domains/general_callbacks.py:111
-msgid ""
-"\n"
-"relaydomain; name; target host; service; enabled; verify recipients \n"
-"relaydomainalias; name; target; enabled \n"
-msgstr "\nrelaydomain; name; target host; service; enabled; verify recipients \nrelaydomainalias; name; target; enabled \n"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:19
-msgid "Maximum number of allowed relay domains for a new administrator"
-msgstr "Max antal tillåtna relay domäner för en ny administratör"
-
-#: extensions/postfix_relay_domains/limits_callbacks.py:27
-msgid "Maximum number of allowed relay domain aliases for a new administrator"
-msgstr "Max antal tillåtna relay domän alias för en ny administratör"
-
-#: extensions/postfix_relay_domains/models.py:59
-msgid "The service name"
-msgstr "Tjänstens namn"
-
-#: extensions/postfix_relay_domains/models.py:80
-msgid "target host"
-msgstr "målvärd"
-
-#: extensions/postfix_relay_domains/models.py:81
-msgid "Remote destination of this domain"
-msgstr "Fjärrmål för den här domänen"
-
-#: extensions/postfix_relay_domains/models.py:89
-msgid "verify recipients"
-msgstr "verifiera mottagare"
-
-#: extensions/postfix_relay_domains/models.py:90
-msgid "Check for valid recipients"
-msgstr "Kontrollera giltiga mottagare"
-
-#: extensions/postfix_relay_domains/models.py:103
-msgid "Relay Domain"
-msgstr "Relay domän"
-
-#: extensions/postfix_relay_domains/models.py:164
-msgid "The relay domain this alias points to"
-msgstr "Den relay domän detta alias pekar mot"
-
-#: extensions/postfix_relay_domains/models.py:195
-#, python-format
-msgid "Relay domain %s does not exist"
-msgstr "Relay domän %s finns inte"
-
-#: extensions/postfix_relay_domains/views.py:28
-msgid "Relay domain created"
-msgstr "Relay domän skapad"
-
-#: extensions/postfix_relay_domains/views.py:33
-msgid "New relay domain"
-msgstr "Ny relay domän"
-
-#: extensions/postfix_relay_domains/views.py:61
-msgid "Relay domain deleted"
-msgstr "Relay domän raderad"
-
-#: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:3
-msgid "Scan"
-msgstr "Skanna"
-
-#: extensions/radicale/__init__.py:34
-msgid "Radicale management"
-msgstr "Radicale hantering"
-
-#: extensions/radicale/__init__.py:38
-msgid ""
-"Management frontend for Radicale, a simple calendar and contact server."
-msgstr "Hanterings frontend för Radicale, en enkel kalender- och kontakt-server"
-
-#: extensions/radicale/app_settings.py:11
-msgid "Server settings"
-msgstr "Serverinställningar"
-
-#: extensions/radicale/app_settings.py:15
-msgid "Server URL"
-msgstr "Server URL"
-
-#: extensions/radicale/app_settings.py:17
-msgid ""
-"The URL of your Radicale server. It will be used to construct calendar URLs."
-msgstr "URL till din Radicale server. Den kommer användas för att konstruera calender URL:er."
-
-#: extensions/radicale/app_settings.py:24
-msgid "Rights management"
-msgstr "Rättighetshantering"
-
-#: extensions/radicale/app_settings.py:27
-msgid "Rights file's path"
-msgstr "Rättighets fil sökväg"
-
-#: extensions/radicale/app_settings.py:30
-msgid "Path to the file that contains rights definition"
-msgstr "Sökväg till filen som innehåller rättighetsdefinitioner"
-
-#: extensions/radicale/app_settings.py:36
-msgid "Allow calendars administration"
-msgstr "Tillåt kalendrars administration"
-
-#: extensions/radicale/app_settings.py:39
-msgid "Allow domain administrators to manage user calendars (read and write)"
-msgstr "Tillåt domänadmininstratörer att ändra användares kalendrar (läsa och skriva)"
-
-#: extensions/radicale/forms.py:73
-#: extensions/radicale/templates/radicale/accessrule.html:6
-msgid "Read"
-msgstr "Läsa"
-
-#: extensions/radicale/forms.py:76
-#: extensions/radicale/templates/radicale/accessrule.html:7
-msgid "Write"
-msgstr "Skriva"
-
-#: extensions/radicale/forms.py:134
-#, python-format
-msgid "Mailbox %s does not exist"
-msgstr "Brevlåda %s existerar inte"
-
-#: extensions/radicale/forms.py:157 extensions/radicale/forms.py:192
-msgid "Rights"
-msgstr "Rättigheter"
-
-#: extensions/radicale/forms.py:162
-msgid "New calendar"
-msgstr "Ny kalendrar"
-
-#: extensions/radicale/forms.py:174 extensions/radicale/views.py:131
-msgid "Calendar created"
-msgstr "Kalender skapad"
-
-#: extensions/radicale/forms.py:213 extensions/radicale/views.py:168
-msgid "Calendar updated"
-msgstr "Kalender uppdaterad"
-
-#: extensions/radicale/general_callbacks.py:15
-msgid "Calendars"
-msgstr "Kalendrar"
-
-#: extensions/radicale/models.py:94
-msgid "User"
-msgstr "Användare"
-
-#: extensions/radicale/models.py:139
-msgid "Shared"
-msgstr "Delad"
-
-#: extensions/radicale/views.py:104 extensions/radicale/views.py:163
-msgid "Calendar removed"
-msgstr "Kalender flyttad"
-
-#: extensions/radicale/views.py:139
-msgid "New shared calendar"
-msgstr "Ny delad kalender"
-
-#: extensions/radicale/views.py:142 extensions/radicale/views.py:179
-#: lib/formutils.py:82
-msgid "Submit"
-msgstr "Skicka"
-
-#: extensions/radicale/templates/radicale/calendar_detail.html:6
-msgid "To access this calendar, use the following address:"
-msgstr "För att få tillgång till denna kalender, använd följande adress:"
-
-#: extensions/radicale/templates/radicale/calendars.html:49
-msgid "Owner"
-msgstr "Ägare"
-
-#: extensions/radicale/templatetags/radicale_tags.py:24
-msgid "Add calendar"
-msgstr "Lägg till kalender"
-
-#: extensions/radicale/templatetags/radicale_tags.py:33
-msgid "Add shared calendar"
-msgstr "Lägg till delad kalender"
-
-#: extensions/radicale/templatetags/radicale_tags.py:50
-msgid "View calendar detail"
-msgstr "Visa kalender detaljer"
-
-#: extensions/radicale/templatetags/radicale_tags.py:68
-#, python-format
-msgid "Edit %s"
-msgstr "Redigera %s"
-
-#: extensions/sievefilters/__init__.py:12
-msgid "Plugin to easily create server-side filters"
-msgstr "Plugin för att enkelt skapa filter på serversidan"
-
-#: extensions/sievefilters/__init__.py:18
-msgid "Sieve filters"
-msgstr "Sieve filter"
-
-#: extensions/sievefilters/__init__.py:19
-#: extensions/sievefilters/general_callbacks.py:14
-#: extensions/sievefilters/templates/sievefilters/index.html:4
-msgid "Message filters"
-msgstr "Meddelandefilter"
-
-#: extensions/sievefilters/app_settings.py:19
-msgid "ManageSieve settings"
-msgstr "ManageSieve inställningar"
-
-#: extensions/sievefilters/app_settings.py:24
-msgid "Address of your MANAGESIEVE server"
-msgstr "Adressen till din MANAGESIEVE server"
-
-#: extensions/sievefilters/app_settings.py:31
-msgid "Listening port of your MANAGESIEVE server"
-msgstr "MANAGESIEVE server lyssnar på port"
-
-#: extensions/sievefilters/app_settings.py:36
-msgid "Connect using STARTTLS"
-msgstr "Anslut med STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:38
-msgid "Use the STARTTLS extension"
-msgstr "Använd STARTTLS"
-
-#: extensions/sievefilters/app_settings.py:42
-msgid "Authentication mechanism"
-msgstr "Autentiseringsmekanism"
-
-#: extensions/sievefilters/app_settings.py:45
-msgid "Prefered authentication mechanism"
-msgstr "Önskad autentiseringsmekanism"
-
-#: extensions/sievefilters/app_settings.py:57
-msgid "Editor mode"
-msgstr "Redigeringsläge"
-
-#: extensions/sievefilters/app_settings.py:59
-msgid "Select the mode you want the editor to work in"
-msgstr "Välj det läge du vill redigeraren att arbeta i"
-
-#: extensions/sievefilters/forms.py:18
-msgid "Check to activate this filters set"
-msgstr "Markera för att aktivera denna filter regel"
-
-#: extensions/sievefilters/forms.py:68
-msgid "All of the following"
-msgstr "Alla av följande"
-
-#: extensions/sievefilters/forms.py:69
-msgid "Any of the following"
-msgstr "Någon av följande"
-
-#: extensions/sievefilters/forms.py:76
-msgid "contains"
-msgstr "innehåller"
-
-#: extensions/sievefilters/forms.py:77
-msgid "does not contain"
-msgstr "innehåller inte"
-
-#: extensions/sievefilters/forms.py:78
-msgid "is"
-msgstr "är"
-
-#: extensions/sievefilters/forms.py:79
-msgid "is not"
-msgstr "är inte"
-
-#: extensions/sievefilters/forms.py:84
-msgid "Sender"
-msgstr "Avsändare"
-
-#: extensions/sievefilters/forms.py:85
-msgid "Recipient"
-msgstr "Mottagare"
-
-#: extensions/sievefilters/forms.py:86 extensions/webmail/forms.py:84
-#: extensions/webmail/templates/webmail/compose.html:15
-msgid "Cc"
-msgstr "Cc"
-
-#: extensions/sievefilters/forms.py:87
-msgid "Size"
-msgstr "Storlek"
-
-#: extensions/sievefilters/forms.py:88
-msgid "is greater than"
-msgstr "är större än"
-
-#: extensions/sievefilters/forms.py:89
-msgid "is less than"
-msgstr "är mindre än"
-
-#: extensions/sievefilters/forms.py:93
-msgid "Move message to"
-msgstr "Flytta meddelande till"
-
-#: extensions/sievefilters/forms.py:95
-msgid "Redirect message to"
-msgstr "Omdirigera meddelande till"
-
-#: extensions/sievefilters/forms.py:110
-msgid "Wrong filter name"
-msgstr "Fel filter namn"
-
-#: extensions/sievefilters/lib.py:41
-msgid "Connection to MANAGESIEVE server failed, check your configuration"
-msgstr "Anslutning till MANAGESIEVE servern misslyckades, kontrollera din konfiguration"
-
-#: extensions/sievefilters/lib.py:86
-msgid "Not enough space on server"
-msgstr "Inte tillräckligt med utrymme på servern"
-
-#: extensions/sievefilters/views.py:80
-msgid "Failed to retrieve filters set"
-msgstr "Det gick inte att hämta filteruppsättning"
-
-#: extensions/sievefilters/views.py:141
-#: extensions/sievefilters/templatetags/sfilters_tags.py:35
-msgid "New filter"
-msgstr "Nytt filter"
-
-#: extensions/sievefilters/views.py:149
-msgid "Filter created"
-msgstr "Filter krashade"
-
-#: extensions/sievefilters/views.py:163
-#: extensions/sievefilters/templatetags/sfilters_tags.py:78
-msgid "Edit filter"
-msgstr "Redigera filter"
-
-#: extensions/sievefilters/views.py:172
-msgid "Filter modified"
-msgstr "Filter modifierat"
-
-#: extensions/sievefilters/views.py:195
-msgid "Filter removed"
-msgstr "Filter raderat"
-
-#: extensions/sievefilters/views.py:196
-msgid "Failed to remove filter"
-msgstr "Det gick inte att radera filtret"
-
-#: extensions/sievefilters/views.py:211
-msgid "Filters set saved"
-msgstr "Filter uppsättning sparat"
-
-#: extensions/sievefilters/views.py:227
-msgid "Filters set created"
-msgstr "Filter uppsättning skapat"
-
-#: extensions/sievefilters/views.py:231
-msgid "Create a new filters set"
-msgstr "Skapa ny filteruppsättning"
-
-#: extensions/sievefilters/views.py:250
-msgid "Filters set deleted"
-msgstr "Filter uppsättning raderad"
-
-#: extensions/sievefilters/views.py:263
-msgid "Filters set activated"
-msgstr "Filter uppsättning aktiverad"
-
-#: extensions/sievefilters/templates/sievefilters/filter.html:9
-msgid "Conditions"
-msgstr "Villkor"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:7
-msgid "Active"
-msgstr "Aktivera"
-
-#: extensions/sievefilters/templates/sievefilters/guieditor.html:24
-msgid "No filter defined yet"
-msgstr "Inga filter definierade än"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:82
-msgid "Filter sets"
-msgstr "Filter uppsättning"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:86
-msgid "active"
-msgstr "aktivera"
-
-#: extensions/sievefilters/templates/sievefilters/index.html:101
-msgid ""
-"No filters set defined yet. You must create one in order to define filters."
-msgstr "Inga filter uppsättningar definierade. Du måste skapa en uppsättning för att kunna definiera filter."
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:17
-msgid "New filters set"
-msgstr "Ny filter uppsättning"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:46
-msgid "Save filters set"
-msgstr "Spara filter uppsättning"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:54
-msgid "Activate filters set"
-msgstr "Aktivera filter uppsättning"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:59
-msgid "Remove filters set"
-msgstr "Radera filter uppsättning"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:63
-msgid "Download"
-msgstr "Ladda ner"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:86
-msgid "Remove this filter"
-msgstr "Radera detta filter"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:94
-msgid "Move this filter up"
-msgstr "Flytta upp detta filter"
-
-#: extensions/sievefilters/templatetags/sfilters_tags.py:102
-msgid "Move this filter down"
-msgstr "Flytta ner detta filter"
-
-#: extensions/stats/__init__.py:21
-msgid "Graphical statistics about emails traffic using RRDtool"
-msgstr "Grafisk statistik om e-post trafik med hjälp av RRDtool"
-
-#: extensions/stats/__init__.py:29
-#: extensions/stats/templates/stats/index.html:4
-msgid "Graphical statistics"
-msgstr "Grafisk statistik"
-
-#: extensions/stats/app_settings.py:14
-msgid "Path to the log file"
-msgstr "Sökväg till loggfil"
-
-#: extensions/stats/app_settings.py:16
-msgid "Path to log file used to collect statistics"
-msgstr "Sökväg till loggfil som används för att samla in statistik"
-
-#: extensions/stats/app_settings.py:21
-msgid "Directory to store RRD files"
-msgstr "Katalog för lagring av RRD filer"
-
-#: extensions/stats/app_settings.py:23
-msgid "Path to directory where RRD files are stored"
-msgstr "Sökväg till katalog där RRD filer lagras"
-
-#: extensions/stats/graphics.py:98
-msgid "Average traffic (msgs/min)"
-msgstr "Genomsnittlig trafik (meddelanden/min)"
-
-#: extensions/stats/graphics.py:101
-msgid "sent messages"
-msgstr "skickade meddelanden"
-
-#: extensions/stats/graphics.py:102
-msgid "received messages"
-msgstr "mottagna meddelande"
-
-#: extensions/stats/graphics.py:103
-msgid "bounced messages"
-msgstr "studsade meddelanden"
-
-#: extensions/stats/graphics.py:104
-msgid "rejected messages"
-msgstr "avvisade meddelanden"
-
-#: extensions/stats/graphics.py:112
-msgid "Average normal traffic size (bytes/min)"
-msgstr "Genomsnittlig normal trafik (bytes/min)"
-
-#: extensions/stats/graphics.py:115
-msgid "received size"
-msgstr "mottagen storlek"
-
-#: extensions/stats/graphics.py:117
-msgid "sent size"
-msgstr "sänd storlek"
-
-#: extensions/stats/graphics.py:152
-msgid "Mail traffic"
-msgstr "Mail trafik"
-
-#: extensions/stats/views.py:31
-msgid "No statistics available"
-msgstr "Ingen statistik tillgänglig"
-
-#: extensions/stats/views.py:35
-msgid "Day"
-msgstr "Dag"
-
-#: extensions/stats/views.py:36
-msgid "Week"
-msgstr "Vecka"
-
-#: extensions/stats/views.py:37
-msgid "Month"
-msgstr "Månad"
-
-#: extensions/stats/views.py:38
-msgid "Year"
-msgstr "År"
-
-#: extensions/stats/views.py:39
-msgid "Custom"
-msgstr "Anpassad"
-
-#: extensions/stats/views.py:87
-msgid "Unknown graphic set"
-msgstr "Okänt grafisk uppsättning"
-
-#: extensions/stats/views.py:98
-msgid "Bad custom period"
-msgstr "Ogiltig anpassad tid"
-
-#: extensions/stats/templates/stats/index.html:42
-msgid "Search a domain"
-msgstr "Sök en domän"
-
-#: extensions/stats/templates/stats/index.html:75
-msgid "Apply"
-msgstr "Applicera"
-
-#: extensions/webmail/__init__.py:13
-msgid "Simple IMAP webmail"
-msgstr "Enkel IMAP webmail"
-
-#: extensions/webmail/app_settings.py:14
-msgid "Maximum attachment size"
-msgstr "Maximal storlek för bilaga"
-
-#: extensions/webmail/app_settings.py:16
-msgid "Maximum attachment size in bytes (or KB, MB, GB if specified)"
-msgstr "Största storlek på bifogad fil i byte (eller KB, MB, GB om det anges)"
-
-#: extensions/webmail/app_settings.py:19
-msgid "IMAP settings"
-msgstr "IMAP inställningar"
-
-#: extensions/webmail/app_settings.py:24
-msgid "Address of your IMAP server"
-msgstr "Adressen till din IMAP-server"
-
-#: extensions/webmail/app_settings.py:30
-msgid "Use a secured connection to access IMAP server"
-msgstr "Använd säker anslutning mot IMAP-servern"
-
-#: extensions/webmail/app_settings.py:36
-msgid "Listening port of your IMAP server"
-msgstr "IMAP-server port"
-
-#: extensions/webmail/app_settings.py:39
-msgid "SMTP settings"
-msgstr "SMTP inställningar"
-
-#: extensions/webmail/app_settings.py:44
-msgid "Address of your SMTP server"
-msgstr "Adressen till din SMTP-server"
-
-#: extensions/webmail/app_settings.py:48
-msgid "Secured connection mode"
-msgstr "Använd en säker anslutning"
-
-#: extensions/webmail/app_settings.py:49
-msgid "None"
-msgstr "Ingen"
-
-#: extensions/webmail/app_settings.py:53
-msgid "Use a secured connection to access SMTP server"
-msgstr "Använd säker anslutning mot SMTP-servern"
-
-#: extensions/webmail/app_settings.py:60
-msgid "Listening port of your SMTP server"
-msgstr "SMTP-server port"
-
-#: extensions/webmail/app_settings.py:64
-msgid "Authentication required"
-msgstr "Autentisering krävs"
-
-#: extensions/webmail/app_settings.py:66
-msgid "Server needs authentication"
-msgstr "Servern behöver autentisering"
-
-#: extensions/webmail/app_settings.py:77
-msgid "Default message display mode"
-msgstr "Standard visningsläge för meddelande"
-
-#: extensions/webmail/app_settings.py:79
-msgid "The default mode used when displaying a message"
-msgstr "Standard visningsläge för meddelande"
-
-#: extensions/webmail/app_settings.py:85
-msgid "Enable HTML links display"
-msgstr "Aktivera visning av HTML länkar"
-
-#: extensions/webmail/app_settings.py:86
-msgid "Enable/Disable HTML links display"
-msgstr "Aktivera / inaktivera om HTML länkar skall visas"
-
-#: extensions/webmail/app_settings.py:92
-msgid "Sets the maximum number of messages displayed in a page"
-msgstr "Anger det maximala antalet meddelanden som visas på en sida"
-
-#: extensions/webmail/app_settings.py:97
-msgid "Listing refresh rate"
-msgstr "Lyssning uppdateringsfrekvens"
-
-#: extensions/webmail/app_settings.py:98
-msgid "Automatic folder refresh rate (in seconds)"
-msgstr "Automatisk mapp uppdateringsfrekvens (i sekunder)"
-
-#: extensions/webmail/app_settings.py:103
-msgid "Mailboxes container's width"
-msgstr "Brevlådornas behållares bredd"
-
-#: extensions/webmail/app_settings.py:104
-msgid "The width of the mailbox list container"
-msgstr "Bredden av brevlådans listbehållare"
-
-#: extensions/webmail/app_settings.py:111
-msgid "Trash folder"
-msgstr "Papperskorg katalog"
-
-#: extensions/webmail/app_settings.py:112
-msgid "Folder where deleted messages go"
-msgstr "Katalog där raderade meddelanden hamnar"
-
-#: extensions/webmail/app_settings.py:117
-msgid "Sent folder"
-msgstr "Skickat katalog"
-
-#: extensions/webmail/app_settings.py:118
-msgid "Folder where copies of sent messages go"
-msgstr "Katalog där kopior av skickade meddelanden hamnar"
-
-#: extensions/webmail/app_settings.py:123
-msgid "Drafts folder"
-msgstr "Utkast katalog"
-
-#: extensions/webmail/app_settings.py:124
-msgid "Folder where drafts go"
-msgstr "Katalog där utkast hamnar"
-
-#: extensions/webmail/app_settings.py:127
-msgid "Composing messages"
-msgstr "Komponera meddelanden"
-
-#: extensions/webmail/app_settings.py:131
-msgid "Default editor"
-msgstr "Standard editor"
-
-#: extensions/webmail/app_settings.py:133
-msgid "The default editor to use when composing a message"
-msgstr "Standardredigerare att använda när du skriver ett meddelande"
-
-#: extensions/webmail/app_settings.py:139
-msgid "Signature text"
-msgstr "Signatur text"
-
-#: extensions/webmail/app_settings.py:140
-msgid "User defined email signature"
-msgstr "Användardefinierad e-post signatur"
-
-#: extensions/webmail/app_settings.py:159
-msgid "Value must be a positive integer (> 0)"
-msgstr "Måste vara ett positivt heltal (> 0)"
-
-#: extensions/webmail/exceptions.py:20
-msgid "Server response"
-msgstr "Server svar"
-
-#: extensions/webmail/exceptions.py:34
-msgid "Unknown action"
-msgstr "Okänd åtgärd"
-
-#: extensions/webmail/forms.py:85
-#: extensions/webmail/templates/webmail/compose.html:16
-msgid "Cci"
-msgstr "BCC"
-
-#: extensions/webmail/general_callbacks.py:14
-msgid "Webmail"
-msgstr "Webmail"
-
-#: extensions/webmail/views.py:95
-#, python-format
-msgid "%(count)d message deleted"
-msgid_plural "%(count)d messages deleted"
-msgstr[0] "%(count)d meddelande raderat"
-msgstr[1] "%(count)d meddelanden raderade"
-
-#: extensions/webmail/views.py:128 extensions/webmail/views.py:372
-msgid "Empty mailbox"
-msgstr "Tom brevlåda"
-
-#: extensions/webmail/views.py:158
-msgid "Mailbox created"
-msgstr "Brevlåda skapad"
-
-#: extensions/webmail/views.py:164
-#: extensions/webmail/templatetags/webmail_tags.py:186
-msgid "Create a new mailbox"
-msgstr "Skapa en ny brevlåda"
-
-#: extensions/webmail/views.py:183 extensions/webmail/views.py:218
-msgid "Edit mailbox"
-msgstr "Redigera brevlåda"
-
-#: extensions/webmail/views.py:199
-msgid "Mailbox updated"
-msgstr "Brevlåda uppdaterad"
-
-#: extensions/webmail/views.py:271
-msgid "Failed to save attachment: "
-msgstr "Det gick inte att spara bilaga:"
-
-#: extensions/webmail/views.py:274
-#, python-format
-msgid "Attachment is too big (limit: %s)"
-msgstr "Bilagan är för stor (max:% s)"
-
-#: extensions/webmail/views.py:280
-#: extensions/webmail/templates/webmail/compose_menubar.html:9
-#: extensions/webmail/templates/webmail/headers.html:4
-msgid "Attachments"
-msgstr "Bilagor"
-
-#: extensions/webmail/views.py:297
-msgid "Bad query"
-msgstr "Dålig fråga"
-
-#: extensions/webmail/views.py:309
-msgid "Failed to remove attachment: "
-msgstr "Misslyckades med att radera bilaga:"
-
-#: extensions/webmail/views.py:314
-msgid "Unknown attachment"
-msgstr "Okänd bilaa"
-
-#: extensions/webmail/lib/imapemail.py:245
-msgid "wrote:"
-msgstr "skrev:"
-
-#: extensions/webmail/lib/imapemail.py:312
-#: extensions/webmail/lib/imapemail.py:315
-msgid "Original message"
-msgstr "Orginalmeddelande"
-
-#: extensions/webmail/lib/imaputils.py:245
-msgid "Failed to retrieve hierarchy delimiter"
-msgstr "Det gick inte att hämta hierarki avgränsare"
-
-#: extensions/webmail/lib/imaputils.py:288
-#, python-format
-msgid "Connection to IMAP server failed: %s"
-msgstr "Anslutning till IMAP servern misslyckades: %s"
-
-#: extensions/webmail/templates/webmail/attachments.html:8
-msgid "Attach"
-msgstr "Bifoga"
-
-#: extensions/webmail/templates/webmail/attachments.html:12
-msgid "Uploading.."
-msgstr "Laddar upp..."
-
-#: extensions/webmail/templates/webmail/folder.html:6
-msgid "Parent mailbox"
-msgstr "Brevlådas förälder"
-
-#: extensions/webmail/templates/webmail/index.html:43
-msgid "Compose"
-msgstr "Skriva"
-
-#: extensions/webmail/templatetags/webmail_tags.py:29
-msgid "Reply"
-msgstr "Svara"
-
-#: extensions/webmail/templatetags/webmail_tags.py:34
-msgid "Reply all"
-msgstr "Svara alla"
-
-#: extensions/webmail/templatetags/webmail_tags.py:48
-msgid "Display options"
-msgstr "Visnings alternativ"
-
-#: extensions/webmail/templatetags/webmail_tags.py:52
-msgid "Activate links"
-msgstr "Aktivera länkar"
-
-#: extensions/webmail/templatetags/webmail_tags.py:54
-msgid "Disable links"
-msgstr "Avaktivera länkar"
-
-#: extensions/webmail/templatetags/webmail_tags.py:78
-msgid "Send"
-msgstr "Skicka"
-
-#: extensions/webmail/templatetags/webmail_tags.py:102
-msgid "Mark as read"
-msgstr "Markera läst"
-
-#: extensions/webmail/templatetags/webmail_tags.py:106
-msgid "Mark as unread"
-msgstr "Markera oläst"
-
-#: extensions/webmail/templatetags/webmail_tags.py:116
-msgid "Empty folder"
-msgstr "Töm katalog"
-
-#: extensions/webmail/templatetags/webmail_tags.py:194
-msgid "Edit the selected mailbox"
-msgstr "Redigera vald brevlåda"
-
-#: extensions/webmail/templatetags/webmail_tags.py:199
-msgid "Remove the selected mailbox"
-msgstr "Radera vald brevlåda"
-
-#: extensions/webmail/templatetags/webmail_tags.py:203
-msgid "Compress folder"
-msgstr "Komprimera katalog"
-
-#: lib/dbutils.py:36
+"Var vänlig rapportera eventuella fel eller ge förslag på mailinglistan ."
+"
\n"
+#: demo/views.py:19 demo/views.py:45
+msgid "Message sent"
+msgstr "Meddelande sänt"
+#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Anslutning till databasen %s är inte konfigurerad"
-
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Tillstånd nekas: %s"
-
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Tillstånd nekas"
-
-#: lib/formutils.py:347 lib/formutils.py:355
+#: lib/form_utils.py:88
+msgid "Submit"
+msgstr "Skicka"
+#: lib/form_utils.py:124 lib/form_utils.py:127
+msgid "Invalid request"
+msgstr "Ogiltig förfrågan"
+#: lib/form_utils.py:358 lib/form_utils.py:366
msgid "Enter a valid domain name"
msgstr "Skriv in ett giltigt domännamn"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "Yes"
msgstr "Ja"
-
-#: lib/formutils.py:404
+#: lib/form_utils.py:415
msgid "No"
msgstr "Nej"
-
-#: lib/ldaputils.py:111
+#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Misslyckades med att uppdatera lösenord: %s"
-
-#: lib/permissions.py:19
+#: lib/permissions.py:22
msgid "Simple user"
msgstr "Enkel användare"
-
-#: lib/permissions.py:21
+#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super administratör"
-
-#: lib/permissions.py:27
+#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Domän administratör"
-
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Ursäkta"
-
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "Den begärda sidan finns inte."
-
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Ett internt fel uppstod."
-
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Sök..."
-
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Från adress"
-
+#: templates/common/email_searchbar.html:17
+msgid "Subject"
+msgstr "Ämne"
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Båda"
-
#: templates/common/error.html:4
msgid "Error:"
msgstr "Fel:"
-
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Hjälp:"
-
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Stäng"
-
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Föregående"
-
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Nästa"
-
#: templates/registration/login.html:8
msgid "Welcome to Modoboa"
msgstr "Välkommen till Modoboa"
-
#: templates/registration/login.html:39
msgid "Remember me"
msgstr "Kom ihåg mig"
-
#: templates/registration/login.html:42
msgid "Log in"
msgstr "Logga in"
diff --git a/modoboa/locale/sv/LC_MESSAGES/djangojs.po b/modoboa/locale/sv/LC_MESSAGES/djangojs.po
index 194b5877b..a1dbe3432 100644
--- a/modoboa/locale/sv/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/sv/LC_MESSAGES/djangojs.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Olle Gustafsson , 2013
# Olle Gustafsson , 2013,2015
@@ -9,177 +9,34 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-11-25 14:23+0100\n"
+"POT-Creation-Date: 2015-02-11 15:07+0100\n"
"PO-Revision-Date: 2015-01-13 15:21+0000\n"
"Last-Translator: Olle Gustafsson \n"
-"Language-Team: Swedish (http://www.transifex.com/projects/p/modoboa/language/sv/)\n"
+"Language-Team: Swedish (http://www.transifex.com/projects/p/modoboa/language/"
+"sv/)\n"
+"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: sv\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Inga fler logg poster att visa"
-
-#: extensions/admin/static/admin/js/admin.js:102
-msgid "No more domain to show"
-msgstr "Inga fler domäner att visa"
-
-#: extensions/admin/static/admin/js/admin.js:113
-msgid "Do not delete domain directory"
-msgstr "Radera inte domän katalog"
-
-#: extensions/admin/static/admin/js/admin.js:115
-msgid "This operation will remove ALL data associated to this domain."
-msgstr "Denna åtgärd kommer radera ALL data associerad med den här domänen."
-
-#: extensions/admin/static/admin/js/admin.js:116
-msgid ""
-"This operation will remove all data associated to this domain, excepting "
-"accounts."
-msgstr "Den här operationen raderar all data som är associerad med denna domän, förutom konton."
-
-#: extensions/admin/static/admin/js/admin.js:198
-msgid "No domain administrator defined"
-msgstr "Ingen domänadministratör definierad"
-
-#: extensions/admin/static/admin/js/admin.js:253
-#: extensions/admin/static/admin/js/admin.js:309
-msgid "No more identity to show"
-msgstr "Inga fler konton att visa"
-
-#: extensions/admin/static/admin/js/admin.js:283
-msgid "Do not delete mailbox directory"
-msgstr "Radera inte brevlådans katalog"
-
-#: extensions/admin/static/admin/js/admin.js:312
-msgid "No more quota to show"
-msgstr "Ingen mer kvota att visa"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:19
-msgid "No more message to show"
-msgstr "Inga fler meddelanden att visa"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:270
-msgid "Release this selection?"
-msgstr "Släpp markerat urval?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:274
-msgid "Delete this selection?"
-msgstr "Radera markerat urval?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:314
-msgid "Mark this selection as spam?"
-msgstr "Markera detta val som skräppost?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:329
-msgid "Mark this selection as non-spam?"
-msgstr "Markera detta val som icke-skräppost?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:354
-#: extensions/amavis/static/amavis/js/selfservice.js:17
-msgid "Release this message?"
-msgstr "Släpp detta meddelande?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:358
-#: extensions/amavis/static/amavis/js/selfservice.js:21
-msgid "Delete this message?"
-msgstr "Radera detta meddelande?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:373
-msgid "Mark as spam?"
-msgstr "Markera som skräppost?"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:389
-msgid "Mark as non-spam?"
-msgstr "Markera som icke-skräppost"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:407
-msgid "View full headers"
-msgstr "Visa meddelandehuvud"
-
-#: extensions/amavis/static/amavis/js/quarantine.js:412
-msgid "Hide full headers"
-msgstr "Göm meddelandehuvud"
-
-#: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49
-msgid "Services updated"
-msgstr "Tjänster uppdaterade"
-
-#: extensions/radicale/static/radicale/js/radicale.js:19
-msgid "No more calendar to show"
-msgstr "Inga fler kalendrar att visa"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:14
-msgid "Remove this filter?"
-msgstr "Radera detta filter?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:107
-msgid "Save changes?"
-msgstr "Spara ändringar?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:129
-msgid "Remove filters set?"
-msgstr "Radera filteruppsättning?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:146
-msgid "Activate this filters set?"
-msgstr "Aktivera filteruppsättning?"
-
-#: extensions/sievefilters/static/sievefilters/js/lib.js:154
-#: extensions/sievefilters/static/sievefilters/js/lib.js:203
-msgid "active"
-msgstr "aktivera"
-
-#: extensions/stats/static/stats/js/stats.js:43
-msgid "Search a domain"
-msgstr "Sök domän"
-
-#: extensions/webmail/static/webmail/js/webmail.js:188
-msgid "No more message in this mailbox."
-msgstr "Inga fler meddelanden i denna brevlåda"
-
-#: extensions/webmail/static/webmail/js/webmail.js:685
-msgid "Remove the selected mailbox?"
-msgstr "Radera markerad brevlåda?"
-
-#: extensions/webmail/static/webmail/js/webmail.js:698
-msgid "Mailbox removed"
-msgstr "Brevlåda raderad"
-
-#: extensions/webmail/static/webmail/js/webmail.js:973
-msgid "Message sent"
-msgstr "Meddelande sänt"
-
-#: extensions/webmail/static/webmail/js/webmail.js:1242
-#, c-format
-msgid "Moving %s message"
-msgid_plural "Moving %s messages"
-msgstr[0] "Flyttar %s meddelande"
-msgstr[1] "Flyttar %s meddelanden"
-
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Varning"
-
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Avbryt"
-
#: static/js/global.js:329
msgid "Internal error"
msgstr "Internt fel"
-
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Inga fler poster att visa"
-
#: static/js/listing.js:46
msgid "Search"
msgstr "Sök"
-
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Sök..."
From 5cfb8bf5a30a2fc25fa984d20df5eb3216b45a66 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Feb 2015 15:10:54 +0100
Subject: [PATCH 09/25] Don't check extensions
---
modoboa/core/commands/templates/settings.py.tpl | 10 ----------
tests/install_from_scratch.py | 8 +-------
2 files changed, 1 insertion(+), 17 deletions(-)
diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl
index c19db186e..c4ef22677 100644
--- a/modoboa/core/commands/templates/settings.py.tpl
+++ b/modoboa/core/commands/templates/settings.py.tpl
@@ -57,14 +57,6 @@ MODOBOA_APPS = (
'modoboa.core',
'modoboa.lib',
# Modoboa extensions here.
- 'modoboa.extensions.postfix_relay_domains',
- 'modoboa.extensions.limits',
- 'modoboa.extensions.postfix_autoreply',
- 'modoboa.extensions.webmail',
- 'modoboa.extensions.stats',
- 'modoboa.extensions.sievefilters',
- 'modoboa.extensions.radicale',
- {% if not amavis_conn %}#{% endif %}'modoboa.extensions.amavis',
# Tools from here
#'modoboa.tools.pfxadmin_migrate',
@@ -120,8 +112,6 @@ DATABASES = { {{ default_conn|safe }}
{{ amavis_conn|safe }}{% endif %}
}
-DATABASE_ROUTERS = ["modoboa.extensions.amavis.dbrouter.AmavisRouter"]
-
# Internationalization
# https://docs.djangoproject.com/en/1.6/topics/i18n/
diff --git a/tests/install_from_scratch.py b/tests/install_from_scratch.py
index fa2663afe..265ece7c2 100644
--- a/tests/install_from_scratch.py
+++ b/tests/install_from_scratch.py
@@ -21,14 +21,8 @@ class DeployTest(unittest.TestCase):
def tearDown(self):
path = os.path.join(self.workdir, self.projname)
core_apps = ["modoboa.core", "modoboa.lib"]
- extensions = [
- "admin", "limits", "postfix_relay_domains", "radicale",
- "postfix_autoreply"
- ]
- cmd = "python manage.py test {0} {1}".format(
+ cmd = "python manage.py test {0}".format(
" ".join(core_apps),
- " ".join(["modoboa.extensions.{0}".format(extension)
- for extension in extensions])
)
code, output = exec_cmd(cmd, capture_output=False, cwd=path)
self.assertEqual(code, 0)
From 53aa55e26978ef703e3fd4fa30d7d75709d85e8d Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 18 Feb 2015 15:02:22 +0100
Subject: [PATCH 10/25] Deploy extensions using pip.
---
modoboa/core/commands/deploy.py | 101 ++++++++++--------
.../core/commands/templates/settings.py.tpl | 25 ++---
2 files changed, 64 insertions(+), 62 deletions(-)
diff --git a/modoboa/core/commands/deploy.py b/modoboa/core/commands/deploy.py
index e3802e229..6c426be39 100644
--- a/modoboa/core/commands/deploy.py
+++ b/modoboa/core/commands/deploy.py
@@ -5,9 +5,14 @@
import getpass
import os
import shutil
+import subprocess
import sys
-import subprocess
+try:
+ import pip
+except ImportError:
+ sys.stderr.write("Error: pip is required to install extensions.\n")
+ sys.exit(2)
import django
from django.core import management
@@ -45,20 +50,13 @@ class DeployCommand(Command):
super(DeployCommand, self).__init__(*args, **kwargs)
self._parser.add_argument('name', type=str,
help='The name of your Modoboa instance')
- self._parser.add_argument(
- '--with-amavis', action='store_true', default=False,
- help='Include amavis configuration'
- )
self._parser.add_argument(
'--collectstatic', action='store_true', default=False,
help='Run django collectstatic command'
)
self._parser.add_argument(
- '--dburl', type=str, nargs=1, default=None,
- help='The database-url for your modoboa instance')
- self._parser.add_argument(
- '--amavis_dburl', type=str, nargs=1, default=None,
- help='The database-url for your amavis instance')
+ '--dburl', type=str, nargs="+", default=None,
+ help='A database-url with a name')
self._parser.add_argument(
'--domain', type=str, default=None,
help='The domain under which you want to deploy modoboa')
@@ -74,6 +72,10 @@ class DeployCommand(Command):
'--devel', action='store_true', default=False,
help='Create a development instance'
)
+ self._parser.add_argument(
+ '--extensions', type=str, nargs='*',
+ help="The list of extension to deploy"
+ )
def _exec_django_command(self, name, cwd, *args):
"""Run a django command for the freshly created project
@@ -136,6 +138,27 @@ class DeployCommand(Command):
info['PASSWORD'] = getpass.getpass('Password: ')
return info
+ def install_extensions(self, extensions):
+ """Install one or more extensions.
+
+ Return the list of extensions providing settings we must
+ include in the final configuration.
+
+ """
+ if "all" in extensions:
+ # Retrieve official extension list from the API
+ return
+ pip_args = ["install"] + extensions
+ pip.main(pip_args)
+ extra_settings = []
+ for extension in extensions:
+ module = __import__(extension, locals(), globals(), [])
+ basedir = os.path.dirname(module.__file__)
+ if not os.path.exists("{0}/settings.py".format(basedir)):
+ continue
+ extra_settings.append(extension)
+ return extra_settings
+
def handle(self, parsed_args):
django.setup()
management.call_command(
@@ -144,40 +167,24 @@ class DeployCommand(Command):
path = "%(name)s/%(name)s" % {'name': parsed_args.name}
sys.path.append(parsed_args.name)
- t = Template(DBCONN_TPL)
-
+ conn_tpl = Template(DBCONN_TPL)
+ connections = {}
if parsed_args.dburl:
- info = dj_database_url.config(default=parsed_args.dburl[0])
- # In case the user fails to supply a valid database url,
- # fallback to manual mode
- if not info:
- print "There was a problem with your database-url. \n"
- info = self.ask_db_info()
- # If we set this earlier, our fallback method will never
- # be triggered
- info['conn_name'] = 'default'
+ for dburl in parsed_args.dburl:
+ conn_name, url = dburl.split(":", 1)
+ info = dj_database_url.config(default=url)
+ # In case the user fails to supply a valid database url,
+ # fallback to manual mode
+ if not info:
+ print "There was a problem with your database-url. \n"
+ info = self.ask_db_info(conn_name)
+ # If we set this earlier, our fallback method will never
+ # be triggered
+ info['conn_name'] = conn_name
+ connections[conn_name] = conn_tpl.render(Context(info))
else:
- info = self.ask_db_info()
-
- default_conn = t.render(Context(info))
-
- if parsed_args.with_amavis:
- if parsed_args.amavis_dburl:
- amavis_info = dj_database_url.config(
- default=parsed_args.amavis_dburl[0])
- # In case the user fails to supply a valid database
- # url, fallback to manual mode
- if not amavis_info:
- amavis_info = self.ask_db_info('amavis')
- # If we set this earlier, our fallback method will
- # never be triggered
- amavis_info['conn_name'] = 'amavis'
- else:
- amavis_info = self.ask_db_info('amavis')
-
- amavis_conn = t.render(Context(amavis_info))
- else:
- amavis_conn = None
+ connections["default"] = conn_tpl.render(
+ Context(self.ask_db_info()))
if parsed_args.domain:
allowed_host = parsed_args.domain
@@ -188,6 +195,10 @@ class DeployCommand(Command):
if not allowed_host:
allowed_host = "localhost"
+ extra_settings = []
+ if parsed_args.extensions:
+ extra_settings = self.install_extensions(parsed_args.extensions)
+
bower_components_dir = os.path.realpath(
os.path.join(os.path.dirname(__file__), "../../bower_components")
)
@@ -195,14 +206,16 @@ class DeployCommand(Command):
mod = __import__(parsed_args.name, globals(), locals(), ['settings'])
tpl = self._render_template(
"%s/settings.py.tpl" % self._templates_dir, {
- 'default_conn': default_conn, 'amavis_conn': amavis_conn,
+ 'db_connections': connections,
'secret_key': mod.settings.SECRET_KEY,
'name': parsed_args.name,
'allowed_host': allowed_host,
'lang': parsed_args.lang,
'timezone': parsed_args.timezone,
'bower_components_dir': bower_components_dir,
- 'devmode': parsed_args.devel
+ 'devmode': parsed_args.devel,
+ 'extensions': parsed_args.extensions,
+ 'extra_settings': extra_settings
}
)
with open("%s/settings.py" % path, "w") as fp:
diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl
index c4ef22677..8ba295fc8 100644
--- a/modoboa/core/commands/templates/settings.py.tpl
+++ b/modoboa/core/commands/templates/settings.py.tpl
@@ -57,9 +57,8 @@ MODOBOA_APPS = (
'modoboa.core',
'modoboa.lib',
# Modoboa extensions here.
-
- # Tools from here
- #'modoboa.tools.pfxadmin_migrate',
+{% for extension in extensions %} '{{ extension }}',
+{% endfor %}
)
INSTALLED_APPS += MODOBOA_APPS
@@ -95,21 +94,8 @@ WSGI_APPLICATION = '{{ name }}.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.6/ref/settings/#databases
-DATABASES = { {{ default_conn|safe }}
- # "pfxadmin" : {
- # "ENGINE" : "django.db.backends.",
- # "NAME" : "",
- # "USER" : "",
- # "PASSWORD" : ""
- # },{% if not amavis_conn %}
- # "amavis": {
- # "ENGINE" : "django.db.backends.",
- # "HOST" : "",
- # "NAME" : "",
- # "USER" : "",
- # "PASSWORD" : ""
- # }{% else %}
- {{ amavis_conn|safe }}{% endif %}
+DATABASES = {
+ {% for conn in db_connections.values %}{{ conn|safe }}{% endfor %}
}
# Internationalization
@@ -177,3 +163,6 @@ LOGGING = {
}
}
}
+{% for extension in extra_settings %}
+import {{ extension }}.settings
+{% endfor %}
From 73abc7c9ea9822113c54e2dd4d6a5e1616b91684 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 18 Feb 2015 15:03:29 +0100
Subject: [PATCH 11/25] Update tests launcher.
---
tests/install_from_scratch.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/install_from_scratch.py b/tests/install_from_scratch.py
index 265ece7c2..b0fa9e45b 100644
--- a/tests/install_from_scratch.py
+++ b/tests/install_from_scratch.py
@@ -55,7 +55,7 @@ class DeployTest(unittest.TestCase):
self.assertEqual(child.exitstatus, 0)
def test_silent(self):
- dburl = "%s://%s:%s@%s/%s" \
+ dburl = "default:%s://%s:%s@%s/%s" \
% (self.dbtype, self.dbuser, self.dbpassword,
self.dbhost, self.projname)
cmd = (
From 90c303842bab1448b507c83eefbf117d5ac605e6 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 18 Feb 2015 15:46:39 +0100
Subject: [PATCH 12/25] Load postfix maps files from extensions.
fix #686
---
modoboa/core/commands/postfix_maps.py | 190 +++++++-------------------
1 file changed, 53 insertions(+), 137 deletions(-)
diff --git a/modoboa/core/commands/postfix_maps.py b/modoboa/core/commands/postfix_maps.py
index 81a5f3fa5..f10c6e111 100644
--- a/modoboa/core/commands/postfix_maps.py
+++ b/modoboa/core/commands/postfix_maps.py
@@ -4,25 +4,45 @@
import datetime
import getpass
-import inspect
import os
import sys
from django.template import Context, Template
+import dj_database_url
+
from . import Command
-
-class MapFilesGenerator(object):
-
- def __init__(self, dbinfo=None):
- """Constructor."""
- self.template = Template("""user = {{ dbuser }}
+MAP_FILE_TEMPLATE = """user = {{ dbuser }}
password = {{ dbpass }}
dbname = {{ dbname }}
hosts = {{ dbhost }}
query = {{ query|safe }}
-""")
+"""
+
+
+class MapFilesRegistry(object):
+
+ """A registry of all map files."""
+
+ def __init__(self):
+ self.files = []
+
+ def add_files(self, files):
+ """Add map files to registry."""
+ self.files += files
+
+
+registry = MapFilesRegistry()
+
+
+class MapFilesGenerator(object):
+
+ """Map files generator."""
+
+ def __init__(self, dbinfo=None):
+ """Constructor."""
+ self.template = Template(MAP_FILE_TEMPLATE)
if dbinfo is None:
self.tpl_context = {
'dbhost': raw_input('Database host: '),
@@ -61,21 +81,16 @@ query = {{ query|safe }}
' '.join(sys.argv[1:]))
print >> fp, content
- def __render_std_maps(self, args):
- """Render standard map files.
-
- (ie. the ones belonging to the 'std' category)
-
- :param args: command line arguments
- """
- for v in globals().values():
- if not inspect.isclass(v) or not issubclass(v, MapFile):
- continue
- if v is MapFile:
- continue
- if v.category not in args.categories:
- continue
- self.__render_map(args, v)
+ def __load_extensions(self, extensions):
+ """Load specified extensions."""
+ if "all" in extensions:
+ # Retrieve extension list from the API
+ return
+ for extension in extensions:
+ try:
+ __import__(extension, locals(), globals(), ["postfix_maps"])
+ except ImportError:
+ sys.stderr.write("Unknown extension {0}".format(extension))
def render(self, args):
"""Render all map files.
@@ -86,11 +101,16 @@ query = {{ query|safe }}
os.mkdir(args.destdir)
except OSError:
pass
- self.__render_std_maps(args)
+ if args.extensions:
+ self.__load_extensions(args.extensions)
+ for mapfile in registry.files:
+ self.__render_map(args, mapfile)
class SQLiteMapFilesGenerator(MapFilesGenerator):
+ """SQLite special generator."""
+
def __init__(self, dbinfo=None):
self.template = Template("""dbpath = {{ dbpath }}
query = {{ query|safe }}
@@ -105,111 +125,6 @@ query = {{ query|safe }}
}
-class MapFile(object):
- category = 'std'
-
-
-class DomainsMap(MapFile):
- filename = 'sql-domains.cf'
- mysql = "SELECT name FROM admin_domain WHERE name='%s' AND enabled=1"
- postgres = "SELECT name FROM admin_domain WHERE name='%s' AND enabled"
- sqlite = "SELECT name FROM admin_domain WHERE name='%s' AND enabled=1"
-
-
-class DomainsAliasesMap(MapFile):
- filename = 'sql-domain-aliases.cf'
- mysql = "SELECT dom.name FROM admin_domain dom INNER JOIN admin_domainalias domal ON dom.id=domal.target_id WHERE domal.name='%s' AND domal.enabled=1 AND dom.enabled=1"
- postgres = "SELECT dom.name FROM admin_domain dom INNER JOIN admin_domainalias domal ON dom.id=domal.target_id WHERE domal.name='%s' AND domal.enabled AND dom.enabled"
- sqlite = "SELECT dom.name FROM admin_domain dom INNER JOIN admin_domainalias domal ON dom.id=domal.target_id WHERE domal.name='%s' AND domal.enabled=1 AND dom.enabled=1"
-
-
-class AliasesMap(MapFile):
- filename = 'sql-aliases.cf'
- mysql = "(SELECT concat(mb.address, '@', dom.name) FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.id IN (SELECT al_mb.mailbox_id FROM admin_alias_mboxes al_mb INNER JOIN admin_alias al ON al_mb.alias_id=al.id INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1)) UNION (SELECT concat(al.address, '@', dom.name) FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE al.id IN (SELECT al_al.to_alias_id FROM admin_alias_aliases al_al INNER JOIN admin_alias al ON al_al.from_alias_id=al.id INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1)) UNION (SELECT al.extmboxes FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1 AND al.extmboxes<>'')"
- postgres = "(SELECT mb.address || '@' || dom.name FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.id IN (SELECT al_mb.mailbox_id FROM admin_alias_mboxes al_mb INNER JOIN admin_alias al ON al_mb.alias_id=al.id INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled AND al.address='%u' AND al.enabled)) UNION (SELECT al.address || '@' || dom.name FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE al.id IN (SELECT al_al.to_alias_id FROM admin_alias_aliases al_al INNER JOIN admin_alias al ON al_al.from_alias_id=al.id INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled AND al.address='%u' AND al.enabled)) UNION (SELECT al.extmboxes FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled AND al.address='%u' AND al.enabled AND al.extmboxes<>'')"
- sqlite = "(SELECT (mb.address || '@' || dom.name) FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.id IN (SELECT al_mb.mailbox_id FROM admin_alias_mboxes al_mb INNER JOIN admin_alias al ON al_mb.alias_id=al.id INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1)) UNION (SELECT (al.address || '@' || dom.name) FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE al.id IN (SELECT al_al.to_alias_id FROM admin_alias_aliases al_al INNER JOIN admin_alias al ON al_al.from_alias_id=al.id INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1)) UNION (SELECT al.extmboxes FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1 AND al.extmboxes<>'')"
-
-
-class DomainAliasesMailboxesMap(MapFile):
- filename = 'sql-domain-aliases-mailboxes.cf'
- mysql = "(SELECT concat(mb.address, '@', dom.name) FROM admin_domainalias domal INNER JOIN admin_domain dom ON domal.target_id=dom.id INNER JOIN admin_mailbox mb ON mb.domain_id=dom.id WHERE domal.name='%d' AND dom.enabled=1 AND mb.address='%u') UNION (SELECT concat(al.address, '@', dom.name) FROM admin_domainalias domal INNER JOIN admin_domain dom ON domal.target_id=dom.id INNER JOIN admin_alias al ON al.domain_id=dom.id WHERE domal.name='%d' AND dom.enabled=1 AND al.address='%u')"
- postgres = "(SELECT mb.address || '@' || dom.name FROM admin_domainalias domal INNER JOIN admin_domain dom ON domal.target_id=dom.id INNER JOIN admin_mailbox mb ON mb.domain_id=dom.id WHERE domal.name='%d' AND dom.enabled AND mb.address='%u') UNION (SELECT al.address || '@' || dom.name FROM admin_domainalias domal INNER JOIN admin_domain dom ON domal.target_id=dom.id INNER JOIN admin_alias al ON al.domain_id=dom.id WHERE domal.name='%d' AND dom.enabled AND al.address='%u')"
- sqlite = "(SELECT mb.address || '@' || dom.name FROM admin_domainalias domal INNER JOIN admin_domain dom ON domal.target_id=dom.id INNER JOIN admin_mailbox mb ON mb.domain_id=dom.id WHERE domal.name='%d' AND dom.enabled=1 AND mb.address='%u') UNION (SELECT al.address || '@' || dom.name FROM admin_domainalias domal INNER JOIN admin_domain dom ON domal.target_id=dom.id INNER JOIN admin_alias al ON al.domain_id=dom.id WHERE domal.name='%d' AND dom.enabled=1 AND al.address='%u')"
-
-
-class MailboxesSelfAliasesMap(MapFile):
- filename = "sql-mailboxes-self-aliases.cf"
- mysql = "SELECT email FROM core_user u INNER JOIN admin_mailbox mb ON mb.user_id=u.id WHERE u.email='%s' AND u.is_active=1"
- postgres = "SELECT email FROM core_user u INNER JOIN admin_mailbox mb ON mb.user_id=u.id WHERE u.email='%s' AND u.is_active"
- sqlite = "SELECT email FROM core_user u INNER JOIN admin_mailbox mb ON mb.user_id=u.id WHERE u.email='%s' AND u.is_active=1"
-
-
-class CatchallAliasesMap(MapFile):
- filename = 'sql-catchall-aliases.cf'
- mysql = "(SELECT concat(mb.address, '@', dom.name) FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.id IN (SELECT al_mb.mailbox_id FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id INNER JOIN admin_alias_mboxes al_mb ON al.id=al_mb.alias_id WHERE al.enabled=1 AND al.address='*' AND dom.name='%d' AND dom.enabled=1)) UNION (SELECT al.extmboxes FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE al.enabled='1' AND al.extmboxes<>'' AND al.address='*' AND dom.name='%d' AND dom.enabled=1)"
- postgres = "(SELECT mb.address || '@' || dom.name FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.id IN (SELECT al_mb.mailbox_id FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id INNER JOIN admin_alias_mboxes al_mb ON al.id=al_mb.alias_id WHERE al.enabled AND al.address='*' AND dom.name='%d' AND dom.enabled)) UNION (SELECT al.extmboxes FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE al.enabled AND al.extmboxes<>'' AND al.address='*' AND dom.name='%d' AND dom.enabled)"
- sqlite = "(SELECT (mb.address || '@' || dom.name) FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.id IN (SELECT al_mb.mailbox_id FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id INNER JOIN admin_alias_mboxes al_mb ON al.id=al_mb.alias_id WHERE al.enabled=1 AND al.address='*' AND dom.name='%d' AND dom.enabled=1)) UNION (SELECT al.extmboxes FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE al.enabled='1' AND al.extmboxes<>'' AND al.address='*' AND dom.name='%d' AND dom.enabled=1)"
-
-
-class MaintainMap(MapFile):
- filename = 'sql-maintain.cf'
- mysql = "SELECT '450 Requested mail action not taken: mailbox unavailable' FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id INNER JOIN admin_mailboxoperation mbop ON mbop.mailbox_id=mb.id WHERE dom.name='%d' AND mb.address='%u' LIMIT 1"
- postgres = "SELECT '450 Requested mail action not taken: mailbox unavailable' FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id INNER JOIN admin_mailboxoperation mbop ON mbop.mailbox_id=mb.id WHERE dom.name='%d' AND mb.address='%u' LIMIT 1"
- sqlite = "SELECT '450 Requested mail action not taken: mailbox unavailable' FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id INNER JOIN admin_mailboxoperation mbop ON mbop.mailbox_id=mb.id WHERE dom.name='%d' AND mb.address='%u' LIMIT 1"
-
-
-class TransportMap(MapFile):
- category = "autoreply"
- filename = 'sql-autoreplies-transport.cf'
- mysql = "SELECT method FROM postfix_autoreply_transport WHERE domain='%s'"
- postgres = "SELECT method FROM postfix_autoreply_transport WHERE domain='%s'"
- sqlite = "SELECT method FROM postfix_autoreply_transport WHERE domain='%s'"
-
-
-class AutoRepliesMap(MapFile):
- category = "autoreply"
- filename = 'sql-autoreplies.cf'
- mysql = "SELECT full_address, autoreply_address FROM postfix_autoreply_alias WHERE full_address='%s'"
- postgres = "SELECT full_address, autoreply_address FROM postfix_autoreply_alias WHERE full_address='%s'"
- sqlite = "SELECT full_address, autoreply_address FROM postfix_autoreply_alias WHERE full_address='%s'"
-
-
-class RelayDomainsMap(MapFile):
- category = "relaydomains"
- filename = "sql-relaydomains.cf"
- mysql = "SELECT name FROM postfix_relay_domains_relaydomain WHERE name='%s' AND enabled=1"
- postgres = "SELECT name FROM postfix_relay_domains_relaydomain WHERE name='%s' AND enabled"
- sqlite = "SELECT name FROM postfix_relay_domains_relaydomain WHERE name='%s' AND enabled=1"
-
-
-class RelayDomainsTransportMap(MapFile):
- category = "relaydomains"
- filename = "sql-relaydomains-transport.cf"
- mysql = "SELECT CONCAT(srv.name, ':[', rdom.target_host, ']') FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled=1 AND rdom.name='%s'"
- postgres = "SELECT srv.name || ':[' || rdom.target_host || ']' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled AND rdom.name='%s'"
- sqlite = "SELECT srv.name || ':[' || rdom.target_host || ']' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled=1 AND rdom.name='%s'"
-
-
-class RelayDomainAliasesTransportMap(MapFile):
- category = "relaydomains"
- filename = "sql-relaydomain-aliases-transport.cf"
- mysql = "SELECT CONCAT(srv.name, ':[', rdom.target_host, ']') FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled=1 AND rdomalias.enabled=1 AND rdomalias.name='%s'"
- postgres = "SELECT srv.name || ':[' || rdom.target_host || ']' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled AND rdomalias.enabled AND rdomalias.name='%s'"
- sqlite = "SELECT srv.name || ':[' || rdom.target_host || ']' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled=1 AND rdomalias.enabled=1 AND rdomalias.name='%s'"
-
-
-class RelayRecipientVerification(MapFile):
- category = "relaydomains"
- filename = "sql-relay-recipient-verification.cf"
- mysql = "SELECT 'reject_unverified_recipient' FROM postfix_relay_domains_relaydomain WHERE verify_recipients=1 AND name='%d'"
- postgres = "SELECT 'reject_unverified_recipient' FROM postfix_relay_domains_relaydomain WHERE verify_recipients AND name='%d'"
- sqlite = (
- "SELECT 'reject_unverified_recipient' "
- "FROM postfix_relay_domains_relaydomain "
- "WHERE verify_recipients=1 AND name='%d'"
- )
-
-
class PostfixMapsCommand(Command):
help = "Generate ready-to-use postfix map files"
@@ -229,16 +144,17 @@ class PostfixMapsCommand(Command):
help="url of Modoboa's database"
)
self._parser.add_argument(
- '--categories', type=str, nargs='*', default=['std'],
- help='Map file categories to generate (choices: std, autoreply)'
+ '--extensions', type=str, nargs='+',
+ help=(
+ 'Generate map files for this extensions '
+ '("all" shortcut available)'
+ )
)
def handle(self, parsed_args):
- """Command entry point.
- """
+ """Command entry point."""
dbinfo = None
if parsed_args.dburl:
- import dj_database_url
dbinfo = dj_database_url.config(default=parsed_args.dburl[0])
if 'sqlite' in dbinfo['ENGINE']:
parsed_args.dbtype = 'sqlite'
@@ -247,7 +163,7 @@ class PostfixMapsCommand(Command):
else:
parsed_args.dbtype = 'mysql'
if parsed_args.dbtype == 'sqlite':
- g = SQLiteMapFilesGenerator(dbinfo)
+ generator = SQLiteMapFilesGenerator(dbinfo)
else:
- g = MapFilesGenerator(dbinfo)
- g.render(parsed_args)
+ generator = MapFilesGenerator(dbinfo)
+ generator.render(parsed_args)
From 419cb4667d42dd5f9a6fd77b4bc77fb73eba3ba5 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 18 Feb 2015 16:42:07 +0100
Subject: [PATCH 13/25] Fix unit tests (temp.)
---
modoboa/core/tests.py | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/modoboa/core/tests.py b/modoboa/core/tests.py
index 8c3608dae..13e983c17 100644
--- a/modoboa/core/tests.py
+++ b/modoboa/core/tests.py
@@ -49,14 +49,17 @@ class ProfileTestCase(ModoTestCase):
class ModoboaAdminCommandTestCase(TestCase):
+
MAP_FILES = {
- "std": [
+ "modoboa_admin": [
"sql-domains.cf", "sql-domain-aliases.cf", "sql-aliases.cf",
"sql-domain-aliases-mailboxes.cf", "sql-catchall-aliases.cf",
"sql-maintain.cf"
],
- "autoreply": ["sql-autoreplies-transport.cf", "sql-autoreplies.cf"],
- "relaydomains": [
+ "modoboa_postfix_autoreply": [
+ "sql-autoreplies-transport.cf", "sql-autoreplies.cf"
+ ],
+ "modoboa_admin_relaydomains": [
"sql-relaydomains.cf", "sql-relaydomains-transport.cf",
"sql-relaydomain-aliases-transport.cf",
"sql-relay-recipient-verification.cf"
@@ -69,19 +72,22 @@ class ModoboaAdminCommandTestCase(TestCase):
def tearDown(self):
exec_cmd("rm -rf {0}".format(self.workdir))
- def _test_maps_generation(self, engine, categories=None):
- if categories is None:
- categories = ["std", "autoreply", "relaydomains"]
+ def _test_maps_generation(self, engine, extensions=None):
+ if extensions is None:
+ extensions = [
+ "modoboa_admin", "modoboa_postfix_autoreply",
+ "modoboa_admin_relaydomains"
+ ]
dburl = "{0}://user:password@localhost/testdb".format(engine)
code, output = exec_cmd(
- "modoboa-admin.py postfix_maps --categories {0}"
+ "modoboa-admin.py postfix_maps --extensions {0}"
" --dburl {1} {2}".format(
- " ".join(categories), dburl, self.workdir
+ " ".join(extensions), dburl, self.workdir
)
)
self.assertEqual(code, 0)
- for category in categories:
- for mapfile in self.MAP_FILES[category]:
+ for extension in extensions:
+ for mapfile in self.MAP_FILES[extension]:
path = "{0}/{1}".format(self.workdir, mapfile)
self.assertTrue(os.path.exists(path))
with open(path) as fpo:
From 5538060c973d688231503b2feed4c35043687566 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Mar 2015 15:48:27 +0100
Subject: [PATCH 14/25] Tests runner for extensions.
---
modoboa/lib/test_utils.py | 42 +++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 modoboa/lib/test_utils.py
diff --git a/modoboa/lib/test_utils.py b/modoboa/lib/test_utils.py
new file mode 100644
index 000000000..5eec2701c
--- /dev/null
+++ b/modoboa/lib/test_utils.py
@@ -0,0 +1,42 @@
+"""Tools for top level testing (ie. when ran by Travis)."""
+
+import os
+import tempfile
+
+from .sysutils import exec_cmd
+
+
+class TestRunnerMixin(object):
+
+ """A test runner for extensions (travis only)."""
+
+ dbtype = "postgres"
+ dbhost = "localhost"
+ projname = "modoboa_test"
+ dbuser = "postgres"
+ dbpassword = ""
+
+ def setUp(self):
+ """Test setup."""
+ self.workdir = tempfile.mkdtemp()
+
+ def test(self):
+ """Run extensions tests."""
+ dburl = "default:{0}://{1}:{2}@{3}/{4}".format(
+ self.dbtype, self.dbuser, self.dbpassword, self.dbhost,
+ self.projname
+ )
+ cmd = (
+ "modoboa-admin.py deploy --collectstatic "
+ "--dburl {0} --extensions {1} --domain {2} {3}"
+ .format(dburl, self.extension, "localhost", self.projname)
+ )
+ code, output = exec_cmd(cmd, cwd=self.workdir)
+ self.assertEqual(code, 0)
+
+ path = os.path.join(self.workdir, self.projname)
+ cmd = "python manage.py test {0}.tests".format(self.extension)
+ code, output = exec_cmd(cmd, capture_output=False, cwd=path)
+ self.assertEqual(code, 0)
+
+
From a5775e0fbb6b79a830a386dfba1ea20e7c310a3b Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 11 Mar 2015 16:28:04 +0100
Subject: [PATCH 15/25] Add an option to skip extensions installation.
---
modoboa/core/commands/deploy.py | 6 +++++-
modoboa/lib/test_utils.py | 3 ++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/modoboa/core/commands/deploy.py b/modoboa/core/commands/deploy.py
index 6c426be39..0dfee4d03 100644
--- a/modoboa/core/commands/deploy.py
+++ b/modoboa/core/commands/deploy.py
@@ -76,6 +76,10 @@ class DeployCommand(Command):
'--extensions', type=str, nargs='*',
help="The list of extension to deploy"
)
+ self._parser.add_argument(
+ '--dont-install-extensions', action='store_true', default=False,
+ help='Do not install extensions using pip'
+ )
def _exec_django_command(self, name, cwd, *args):
"""Run a django command for the freshly created project
@@ -196,7 +200,7 @@ class DeployCommand(Command):
allowed_host = "localhost"
extra_settings = []
- if parsed_args.extensions:
+ if parsed_args.dont_install_extensions and parsed_args.extensions:
extra_settings = self.install_extensions(parsed_args.extensions)
bower_components_dir = os.path.realpath(
diff --git a/modoboa/lib/test_utils.py b/modoboa/lib/test_utils.py
index 5eec2701c..98888069e 100644
--- a/modoboa/lib/test_utils.py
+++ b/modoboa/lib/test_utils.py
@@ -28,7 +28,8 @@ class TestRunnerMixin(object):
)
cmd = (
"modoboa-admin.py deploy --collectstatic "
- "--dburl {0} --extensions {1} --domain {2} {3}"
+ "--dburl {0} --extensions {1} --dont-install-extensions "
+ "--domain {2} {3}"
.format(dburl, self.extension, "localhost", self.projname)
)
code, output = exec_cmd(cmd, cwd=self.workdir)
From 8b554bad79a8a4bab26f39d33910202431ed94ae Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 25 Mar 2015 16:02:28 +0100
Subject: [PATCH 16/25] Load extension list from the API.
---
modoboa/core/commands/deploy.py | 7 +++--
modoboa/core/utils.py | 33 ++------------------
modoboa/lib/api_client.py | 54 +++++++++++++++++++++++++++++++++
3 files changed, 62 insertions(+), 32 deletions(-)
create mode 100644 modoboa/lib/api_client.py
diff --git a/modoboa/core/commands/deploy.py b/modoboa/core/commands/deploy.py
index 0dfee4d03..071e6102e 100644
--- a/modoboa/core/commands/deploy.py
+++ b/modoboa/core/commands/deploy.py
@@ -21,6 +21,7 @@ from django.template import Context, Template
import dj_database_url
from modoboa.core.commands import Command
+from modoboa.lib.api_client import ModoAPIClient
DBCONN_TPL = """
'{{ conn_name }}': {
@@ -150,12 +151,14 @@ class DeployCommand(Command):
"""
if "all" in extensions:
- # Retrieve official extension list from the API
- return
+ official_exts = ModoAPIClient().list_extensions()
+ extensions = [extension["name"] for extension in official_exts]
+
pip_args = ["install"] + extensions
pip.main(pip_args)
extra_settings = []
for extension in extensions:
+ extension = extension.replace("-", "_")
module = __import__(extension, locals(), globals(), [])
basedir = os.path.dirname(module.__file__)
if not os.path.exists("{0}/settings.py".format(basedir)):
diff --git a/modoboa/core/utils.py b/modoboa/core/utils.py
index 979654b14..a33fb5c48 100644
--- a/modoboa/core/utils.py
+++ b/modoboa/core/utils.py
@@ -1,40 +1,13 @@
-"""
-Utility functions.
-"""
-import os
-import pkg_resources
-
-import requests
-from requests.exceptions import RequestException
-
-from django.conf import settings
+"""Utility functions."""
from django.contrib.sites.models import get_current_site
-from versionfield.constants import DEFAULT_NUMBER_BITS
-from versionfield.version import Version
-
from modoboa.lib import parameters
+from modoboa.lib.api_client import ModoAPIClient
def new_version_available(request):
"""Check if a new version of Modoboa is available."""
if parameters.get_admin("CHECK_NEW_VERSIONS") == "no":
return None
- local_version = pkg_resources.get_distribution("modoboa").version
- url = os.path.join(settings.MODOBOA_API_URL, "current_version/")
- site = get_current_site(request)
- try:
- resp = requests.get(url, params={
- "client_version": pkg_resources.get_distribution("modoboa").version,
- "client_site": site
- })
- except RequestException:
- return None
- if resp.status_code != 200:
- return None
- resp = resp.json()
- version = Version(resp["version"], DEFAULT_NUMBER_BITS)
- if version <= Version(local_version, DEFAULT_NUMBER_BITS):
- return None
- return resp
+ return ModoAPIClient().current_version(get_current_site(request))
diff --git a/modoboa/lib/api_client.py b/modoboa/lib/api_client.py
new file mode 100644
index 000000000..19490ad83
--- /dev/null
+++ b/modoboa/lib/api_client.py
@@ -0,0 +1,54 @@
+"""A client for Modoboa's public API."""
+
+import os
+import pkg_resources
+
+import requests
+from requests.exceptions import RequestException
+
+from django.conf import settings
+
+from versionfield.constants import DEFAULT_NUMBER_BITS
+from versionfield.version import Version
+
+
+class ModoAPIClient(object):
+
+ """A simple client for the public API."""
+
+ def __init__(self, api_url=None):
+ """Constructor."""
+ self._api_url = (
+ settings.MODOBOA_API_URL if api_url is None
+ else api_url
+ )
+
+ def __send_request(self, url, params=None):
+ """Send a request to the API."""
+ if params is None:
+ params = {}
+ try:
+ resp = requests.get(url, params=params)
+ except RequestException:
+ return None
+ if resp.status_code != 200:
+ return None
+ return resp.json()
+
+ def current_version(self, site):
+ """Check the latest version."""
+ client_version = pkg_resources.get_distribution("modoboa").version
+ url = os.path.join(self._api_url, "current_version/")
+ params = {"client_version": client_version, "site": site}
+ resp = self.__send_request(url, params)
+ if resp is None:
+ return None
+ version = Version(resp["version"], DEFAULT_NUMBER_BITS)
+ if version <= Version(client_version, DEFAULT_NUMBER_BITS):
+ return None
+ return resp
+
+ def list_extensions(self):
+ """List all official extensions."""
+ url = os.path.join(self._api_url, "extensions/")
+ return self.__send_request(url)
From d1af775b6404a9c8f3a378903ecf8921d5d13f33 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Sat, 4 Apr 2015 13:51:57 +0200
Subject: [PATCH 17/25] Merge extensions and information pages.
Check updates for extensions too.
---
modoboa/core/__init__.py | 7 ++-
modoboa/core/extensions.py | 22 +++++++-
modoboa/core/templates/core/extensions.html | 22 --------
modoboa/core/templates/core/information.html | 59 ++++++++++++++------
modoboa/core/templatetags/core_tags.py | 7 +--
modoboa/core/urls.py | 2 -
modoboa/core/utils.py | 24 +++++++-
modoboa/core/views/admin.py | 20 ++-----
modoboa/lib/api_client.py | 31 ++++++++--
9 files changed, 119 insertions(+), 75 deletions(-)
delete mode 100644 modoboa/core/templates/core/extensions.html
diff --git a/modoboa/core/__init__.py b/modoboa/core/__init__.py
index cc91ec6c1..210c9f167 100644
--- a/modoboa/core/__init__.py
+++ b/modoboa/core/__init__.py
@@ -72,15 +72,16 @@ def check_for_new_version(request, include_all):
"""
Check if a new version of Modoboa is available.
"""
- from modoboa.core.utils import new_version_available
+ from modoboa.core.utils import check_for_updates
if not request.user.is_superuser:
return []
- if new_version_available(request) is None:
+ status, extensions = check_for_updates(request)
+ if not status:
return [{"id": "newversionavailable"}] if include_all else []
return [{
"id": "newversionavailable",
"url": reverse("core:index") + "#info/",
- "text": _("New Modoboa version available"),
+ "text": _("One or more updates are available"),
"level": "info",
}]
diff --git a/modoboa/core/extensions.py b/modoboa/core/extensions.py
index 82e5fd30e..6037c1cd8 100644
--- a/modoboa/core/extensions.py
+++ b/modoboa/core/extensions.py
@@ -3,6 +3,11 @@
from django.conf import settings
from django.conf.urls import include
+from versionfield.constants import DEFAULT_NUMBER_BITS
+from versionfield.version import Version
+
+from modoboa.lib.api_client import ModoAPIClient
+
class ModoExtension(object):
@@ -101,14 +106,29 @@ class ExtensionsPool(object):
extinstance.load()
return result
- def list_all(self):
+ def list_all(self, check_new_versions=False):
"""List all defined extensions."""
result = []
+ if check_new_versions:
+ new_extensions = ModoAPIClient().list_extensions()
+ new_extensions = dict(
+ (ext["name"], ext["version"]) for ext in new_extensions
+ )
+ else:
+ new_extensions = {}
for extname, extdef in self.extensions.iteritems():
if not extdef["show"]:
continue
infos = self.get_extension_infos(extname)
infos["id"] = extname
+ local_version = Version(infos["version"], DEFAULT_NUMBER_BITS)
+ pkgname = infos["name"].replace("_", "-")
+ if pkgname in new_extensions:
+ infos["last_version"] = new_extensions[pkgname]
+ last_version = Version(
+ new_extensions[pkgname], DEFAULT_NUMBER_BITS)
+ if last_version > local_version:
+ infos["update"] = True
result += [infos]
return sorted(result, key=lambda i: i["name"])
diff --git a/modoboa/core/templates/core/extensions.html b/modoboa/core/templates/core/extensions.html
deleted file mode 100644
index 6415135e3..000000000
--- a/modoboa/core/templates/core/extensions.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% load i18n %}
-{% load url from future %}
-
-{% trans "Extensions" %} {% trans "The extension(s) you are using" %}
-
-
-
- {% trans "Name" %}
- {% trans "Version" %}
- {% trans "Description" %}
-
-
-
- {% for extension in extensions %}
-
- {{ extension.label }}
- {{ extension.version }}
- {{ extension.description }}
-
- {% endfor %}
-
-
diff --git a/modoboa/core/templates/core/information.html b/modoboa/core/templates/core/information.html
index 23f6264c2..9d1fff110 100644
--- a/modoboa/core/templates/core/information.html
+++ b/modoboa/core/templates/core/information.html
@@ -1,25 +1,50 @@
{% load i18n core_tags lib_tags %}
{% trans "Information" %} {% trans "Various information about Modoboa" %}
-{% if new_version %}
+{% if update_avail %}
-
{% trans "An update is available!" %}
- {% blocktrans with version=new_version.version changelog_url=new_version.changelog_url %}
- Modoboa
{{ version }} is available for download. The list of all changes is available
here .
- {% endblocktrans %}
+
{% trans "One or more updates are available!" %}
+
{% trans "Check the following list to find the component(s) that can be updated." %}
{% endif %}
-Modoboa {% get_version %} {% trans "is currently in use." %}
+
+{% trans "Applications" %}
+
+
+
+ {% trans "Name" %}
+ {% trans "Installed version" %}
+ {% trans "Last version" %}
+ {% trans "Description" %}
+
+
+
+ {% for extension in extensions %}
+
+ {{ extension.label }}
+ {{ extension.version }}
+ {% if extension.update %}{% if extension.changelog_url %}{{ extension.last_version }} {% else %}{{ extension.last_version }}{% endif %} {% else %}{{ extension.last_version }}{% endif %}
+ {{ extension.description }}
+
+ {% endfor %}
+
+
{% trans "Active users" %}
-
-
- {% trans "Name" %}
- {% trans "Group name" %}
- {% trans "Last login" %}
-
- {% connected_users as users %}{% for u in users %}
- {{ u.username }}
- {{ u.group }}
- {{ u.last_login }}
- {% endfor %}
+
+
+
+ {% trans "Name" %}
+ {% trans "Group name" %}
+ {% trans "Last login" %}
+
+
+
+ {% connected_users as users %}{% for u in users %}
+
+ {{ u.username }}
+ {{ u.group }}
+ {{ u.last_login }}
+
+ {% endfor %}
+
diff --git a/modoboa/core/templatetags/core_tags.py b/modoboa/core/templatetags/core_tags.py
index bd50c7eb7..805fa289c 100644
--- a/modoboa/core/templatetags/core_tags.py
+++ b/modoboa/core/templatetags/core_tags.py
@@ -46,11 +46,6 @@ def extensions_menu(selection, user):
@register.simple_tag
def admin_menu(selection, user):
entries = [
- {"name": "extensions",
- "class": "ajaxnav",
- "url": "extensions/",
- "label": _("Extensions"),
- "img": ""},
{"name": "info",
"class": "ajaxnav",
"url": "info/",
@@ -151,7 +146,7 @@ def visirule(field):
% (rule["field"], rule["value"])
-@register.simple_tag
+@register.assignment_tag
def get_version():
import pkg_resources
return pkg_resources.get_distribution("modoboa").version
diff --git a/modoboa/core/urls.py b/modoboa/core/urls.py
index cf03287fa..e4fba293d 100644
--- a/modoboa/core/urls.py
+++ b/modoboa/core/urls.py
@@ -15,8 +15,6 @@ urlpatterns = patterns(
name="parameter_listl"),
url(r'^core/parameters/save/$', 'modoboa.core.views.admin.saveparameters',
name="parameter_save"),
- url(r'^core/extensions/$', 'modoboa.core.views.admin.viewextensions',
- name="extension_list"),
url(r'^core/info/$', 'modoboa.core.views.admin.information',
name="information"),
url(r'^core/logs/$', 'modoboa.core.views.admin.logs', name="log_list"),
diff --git a/modoboa/core/utils.py b/modoboa/core/utils.py
index a33fb5c48..fef7450b2 100644
--- a/modoboa/core/utils.py
+++ b/modoboa/core/utils.py
@@ -1,13 +1,31 @@
"""Utility functions."""
+from django.utils.translation import ugettext as _
+
from django.contrib.sites.models import get_current_site
+from modoboa.core.extensions import exts_pool
from modoboa.lib import parameters
from modoboa.lib.api_client import ModoAPIClient
-def new_version_available(request):
+def check_for_updates(request):
"""Check if a new version of Modoboa is available."""
if parameters.get_admin("CHECK_NEW_VERSIONS") == "no":
- return None
- return ModoAPIClient().current_version(get_current_site(request))
+ return False, []
+ client = ModoAPIClient()
+ extensions = exts_pool.list_all(True)
+ extensions = [{
+ "label": "Modoboa",
+ "description": _("The core part of Modoboa"),
+ "update": client.new_core_version(get_current_site(request)),
+ "last_version": client.latest_core_version,
+ "changelog_url": client.changelog_url,
+ "version": client.local_core_version
+ }] + extensions
+ update_avail = False
+ for extension in extensions:
+ if "update" in extension:
+ update_avail = True
+ break
+ return update_avail, extensions
diff --git a/modoboa/core/views/admin.py b/modoboa/core/views/admin.py
index f1844ff76..56d0b19df 100644
--- a/modoboa/core/views/admin.py
+++ b/modoboa/core/views/admin.py
@@ -8,8 +8,9 @@ from django.shortcuts import render
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
+from modoboa.core.extensions import exts_pool
from modoboa.core.models import Log
-from modoboa.core.utils import new_version_available
+from modoboa.core.utils import check_for_updates
from modoboa.lib import events, parameters
from modoboa.lib.listing import get_sort_order, get_listing_page
from modoboa.lib.web_utils import (
@@ -51,25 +52,14 @@ def saveparameters(request):
return render_to_json_response(_("Parameters saved"))
-@login_required
-@user_passes_test(lambda u: u.is_superuser)
-def viewextensions(request, tplname='core/extensions.html'):
- """List available extensions."""
- from modoboa.core.extensions import exts_pool
-
- exts = exts_pool.list_all()
- return render_to_json_response({
- "callback": "extensions",
- "content": _render_to_string(request, tplname, {"extensions": exts})
- })
-
-
@login_required
@user_passes_test(lambda u: u.is_superuser)
def information(request, tplname="core/information.html"):
+ status, extensions = check_for_updates(request)
return render_to_json_response({
"content": render_to_string(tplname, {
- "new_version": new_version_available(request)
+ "update_avail": status,
+ "extensions": extensions,
}),
})
diff --git a/modoboa/lib/api_client.py b/modoboa/lib/api_client.py
index 19490ad83..698ce6141 100644
--- a/modoboa/lib/api_client.py
+++ b/modoboa/lib/api_client.py
@@ -22,6 +22,9 @@ class ModoAPIClient(object):
settings.MODOBOA_API_URL if api_url is None
else api_url
)
+ self._local_core_version = None
+ self._latest_core_version = None
+ self.changelog_url = None
def __send_request(self, url, params=None):
"""Send a request to the API."""
@@ -35,18 +38,34 @@ class ModoAPIClient(object):
return None
return resp.json()
- def current_version(self, site):
+ @property
+ def local_core_version(self):
+ """Return the version installed locally."""
+ if self._local_core_version is None:
+ self._local_core_version = pkg_resources.get_distribution(
+ "modoboa").version
+ return self._local_core_version
+
+ @property
+ def latest_core_version(self):
+ """Return the latest core version."""
+ if self._latest_core_version is None:
+ return self._local_core_version
+ return self._latest_core_version
+
+ def new_core_version(self, site):
"""Check the latest version."""
- client_version = pkg_resources.get_distribution("modoboa").version
url = os.path.join(self._api_url, "current_version/")
- params = {"client_version": client_version, "site": site}
+ params = {"client_version": self.local_core_version, "site": site}
resp = self.__send_request(url, params)
if resp is None:
return None
version = Version(resp["version"], DEFAULT_NUMBER_BITS)
- if version <= Version(client_version, DEFAULT_NUMBER_BITS):
- return None
- return resp
+ if version <= Version(self.local_core_version, DEFAULT_NUMBER_BITS):
+ return False
+ self._latest_core_version = resp["version"]
+ self.changelog_url = resp["changelog_url"]
+ return True
def list_extensions(self):
"""List all official extensions."""
From abdbf87983cc3fcd56244aea2b062ce7f8e50618 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Sun, 5 Apr 2015 14:29:53 +0200
Subject: [PATCH 18/25] Documentation update
---
doc/conf.py | 10 +-
doc/getting_started/upgrade.rst | 2 +-
doc/plugins/amavis.rst | 302 +-------------------------
doc/plugins/limits.rst | 13 +-
doc/plugins/postfix_autoreply.rst | 46 +---
doc/plugins/postfix_relay_domains.rst | 37 +---
doc/plugins/radicale.rst | 43 +---
doc/plugins/sievefilters.rst | 40 +---
doc/plugins/statistics.rst | 42 +---
doc/plugins/webmail.rst | 66 +-----
10 files changed, 17 insertions(+), 584 deletions(-)
diff --git a/doc/conf.py b/doc/conf.py
index 44f06ec80..741a149d7 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -25,7 +25,9 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = []
+extensions = [
+ 'sphinx.ext.intersphinx',
+]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['.templates']
@@ -41,7 +43,7 @@ master_doc = 'index'
# General information about the project.
project = u'Modoboa'
-copyright = u'2014, Antoine Nguyen'
+copyright = u'2015, Antoine Nguyen'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -219,3 +221,7 @@ man_pages = [
('index', 'modoboa', u'Modoboa Documentation',
[u'Antoine Nguyen'], 1)
]
+
+intersphinx_mapping = {
+ 'amavis': ('http://modoboa-amavis.readthedocs.org/en/latest/', None)
+}
diff --git a/doc/getting_started/upgrade.rst b/doc/getting_started/upgrade.rst
index 230ad644a..eacf67fce 100644
--- a/doc/getting_started/upgrade.rst
+++ b/doc/getting_started/upgrade.rst
@@ -105,7 +105,7 @@ If you plan to use the Radicale extension:
A new feature allows administrators and users to manually train
SpamAssassin in order to customize its behaviour.
-Check :ref:`sa_manual_learning` to know more about this feature.
+Check :ref:`amavis:sa_manual_learning` to know more about this feature.
1.1.6: Few bugfixes
===================
diff --git a/doc/plugins/amavis.rst b/doc/plugins/amavis.rst
index fb5b043c9..268448917 100644
--- a/doc/plugins/amavis.rst
+++ b/doc/plugins/amavis.rst
@@ -4,304 +4,4 @@
Amavisd-new frontend
####################
-This plugin provides a simple management frontend for `amavisd-new
-`_. The supported features are:
-
-* SQL quarantine management : available to administrators or users,
- possibility to delete or release messages
-* Per domain customization (using policies): specify how amavisd-new
- will handle traffic
-
-.. note::
-
- The per-domain policies feature only works for new
- installations. Currently, you can't use modoboa with an existing
- database (ie. with data in ``users`` and ``policies`` tables).
-
-.. note::
-
- This plugin requires amavisd-new version **2.7.0** or higher. If
- you're planning to use the :ref:`selfservice`, you'll need version
- **2.8.0**.
-
-Quick Amavis setup
-==================
-
-By default, amavis doesn't use a database. To configure this
-behaviour, you first need to create a dedicated database. This step is a
-bit manual since no *ready-to-use* SQL schema is provided by
-amavis. The information is located inside README files, one for `MySQL
-`_ and one for `PostgreSQL
-`_.
-
-Then, you must tell amavis to use this database for lookups and
-quarantined messages storing. Here is a working configuration sample::
-
- @lookup_sql_dsn =
- (['DBI::database=;host=;port=', '', ']']);
-
- @storage_sql_dsn =
- (['DBI::database=;host=;port=', '', ']']);
-
- # PostgreSQL users NEED this parameter!
- # MySQL users only need this parameter is email addresses are stored
- # using the VARBINARY type.
- $sql_allow_8bit_address = 1;
-
- $virus_quarantine_method = 'sql:';
- $spam_quarantine_method = 'sql:';
- $banned_files_quarantine_method = 'sql:';
- $bad_header_quarantine_method = 'sql:';
-
- $virus_quarantine_to = 'virus-quarantine';
- $banned_quarantine_to = 'banned-quarantine';
- $bad_header_quarantine_to = 'bad-header-quarantine';
- $spam_quarantine_to = 'spam-quarantine';
-
-Replace values between ``<>`` by yours. To know how to configure
-amavis to allow quarantined messages release, read this :ref:`section
-`.
-
-.. note::
-
- Amavis configuration allows for separate lookup and storage
- databases but Modoboa doesn't support it yet.
-
-Connect Modoboa and Amavis
-==========================
-
-You must tell to Modoboa where it can find the amavis
-database. Inside :file:`settings.py`, add a new connection to the
-``DATABASES`` variable like this::
-
- DATABASES = {
- # Stuff before
- #
- "amavis": {
- "ENGINE" : "",
- "HOST" : "",
- "NAME" : "",
- "USER" : "",
- "PASSWORD" : ""
- }
- }
-
-Replace values between ``<>`` with yours.
-
-Cleanup
--------
-
-Storing quarantined messages to a database can quickly become a
-perfomance killer. Modoboa provides a simple script to periodically
-purge the quarantine database. To use it, add the following line
-inside root's crontab::
-
- 0 0 * * * /manage.py qcleanup
- #
- # Or like this if you use a virtual environment:
- # 0 0 * * * /manage.py qcleanup
-
-Replace ``modoboa_site`` with the path of your Modoboa instance.
-
-By default, messages older than 14 days are automatically purged. You
-can modify this value by changing the ``MAX_MESSAGES_AGE`` parameter
-in the online panel.
-
-.. _amavis_release:
-
-Release messages
-================
-
-To release messages, first take a look at `this page
-`_. It
-explains how to configure amavisd-new to listen somewhere for the
-AM.PDP protocol. This protocol is used to send requests.
-
-Below is an example of a working configuration::
-
- $interface_policy{'SOCK'} = 'AM.PDP-SOCK';
- $interface_policy{'9998'} = 'AM.PDP-INET';
-
- $policy_bank{'AM.PDP-SOCK'} = {
- protocol => 'AM.PDP',
- auth_required_release => 0,
- };
- $policy_bank{'AM.PDP-INET'} = {
- protocol => 'AM.PDP',
- inet_acl => [qw( 127.0.0.1 [::1] )],
- };
-
-Don't forget to update the ``inet_acl`` list if you plan to release from
-the network.
-
-Once amavisd-new is configured, just tell Modoboa where it can find
-the *release server* by modifying the following parameters in the
-online panel:
-
-+--------------------+--------------------+------------------------+
-|Name |Description |Default value |
-+====================+====================+========================+
-|Amavis connection |Mode used to access |unix |
-|mode |the PDP server | |
-+--------------------+--------------------+------------------------+
-|PDP server address |PDP server address |localhost |
-| |(if inet mode) | |
-+--------------------+--------------------+------------------------+
-|PDP server port |PDP server port (if | |
-| |inet mode) 9998 | |
-+--------------------+--------------------+------------------------+
-|PDP server socket |Path to the PDP |/var/amavis/amavisd.sock|
-| |server socket (if | |
-| |unix mode) | |
-+--------------------+--------------------+------------------------+
-
-Deferred release
-----------------
-
-By default, simple users are not allowed to release messages
-themselves. They are only allowed to send release requests to
-administrators.
-
-As administrators are not always available or logged into Modoboa, a
-notification tool is available. It sends reminder e-mails to every
-administrators or domain administrators. To use it, add the following
-example line to root's crontab::
-
- 0 12 * * * /manage.py amnotify --baseurl=''
- #
- # Or like this if you use a virtual environment:
- # 0 12 * * * /manage.py amnotify --baseurl=''
-
-You are free to change the frequency.
-
-.. note::
-
- If you want to let users release their messages alone (not
- recommended), go to the admin panel.
-
-The following parameters are available to let you customize this
-feature:
-
-+--------------------+--------------------+------------------------+
-|Name |Description |Default value |
-+====================+====================+========================+
-|Check requests |Interval between two|30 |
-|interval |release requests | |
-| |checks | |
-+--------------------+--------------------+------------------------+
-|Allow direct release|Allow users to |no |
-| |directly release | |
-| |their messages | |
-+--------------------+--------------------+------------------------+
-|Notifications sender|The e-mail address |notification@modoboa.org|
-| |used to send | |
-| |notitications | |
-+--------------------+--------------------+------------------------+
-
-.. _selfservice:
-
-Self-service mode
-=================
-
-The *self-service* mode lets users act on quarantined messages without
-beeing authenticated. They can:
-
-* View messages
-* Remove messages
-* Release messages (or send release requests)
-
-To access a specific message, they only need the following information:
-
-* Message's unique identifier
-* Message's secret identifier
-
-This information is controlled by *amavis*, which is in charge of
-notifying users when new messages are put into quarantine. Each
-notification (one per message) must embark a direct link containing
-the required identifiers.
-
-To activate this feature, go the administration panel and set the
-**Enable self-service mode** parameter to yes.
-
-The last step is to customize the notification messages amavis
-sends. The most important is to embark a direct link. Take a look at
-the `README.customize `_ file to
-learn what you're allowed to do.
-
-Here is a link example::
-
- http:///quarantine/%i/?rcpt=%R&secret_id=[:secret_id]
-
-.. _sa_manual_learning:
-
-Manual SpamAssassin learning
-============================
-
-It is possible to manually train `SpamAssassin
- `_ using the quarantine's content. By
-train, we mean:
-
-* Mark message(s) as spam (false negative(s))
-
-* Mark message(s) as non-spam (false positive(s))
-
-This feature is available to all users (from super administrators to
-simple users) but not enabled by default.
-
-SpamAssassin configuration
---------------------------
-
-For better performance and to enable the per-user level, SpamAssassin
-must store bayes information into a SQL database.
-
-Create a new database and a new user/password (using your favorite
-database server) and edit the default configuration file
-(:file:`/etc/spamassassin/local.cf`) to add the following lines
-inside:
-
-.. sourcecode:: perl
-
- bayes_store_module Mail::SpamAssassin::BayesStore::
- bayes_sql_dsn
- bayes_sql_username
- bayes_sql_password
-
-Replace values between ``<>`` by yours. Possible values for ``Driver``
-are ``PgSQL`` or ``MySQL`` (non exhaustive list). The syntax for
-``DSN`` depends on the driver you choose. Please consult the official
-documentation.
-
-Enable the feature through Modoboa
-----------------------------------
-
-Manual learning is disabled by default. You can activate it through
-the administration panel (*Modoboa > Paremeters > Amavis*). There two
-learning levels:
-
-#. Global: available to administrators only. A single (global) bayes
- database is shared between everyone.
-
-#. Per domain: available to administrators and domain
- administrators. Each domain can have a dedicated database.
-
-#. Per user: each user can create its own database to customize the
- way SpamAssassin will detect spam.
-
-The domain and user levels are not activated by default, dedicated
-parameters are available through the panel.
-
-.. note::
-
- Domain and user databases are only created the first time someone
- calls the learning feature through the quarantine.
-
-.. warning::
-
- A bayes database needs to reach pre-defined thresholds before it
- can be used by SpamAssassin. The default values are **200** spams
- and **200** hams.
-
-You will find other paramaters related to this feature. You won't need
-to change them most of the time, unless SpamAssassin is hosted on a
-different machine than Modoboa. (in this case, ``spamc`` will be used
-instead of ``sa-learn``).
+`Official documentation `_.
diff --git a/doc/plugins/limits.rst b/doc/plugins/limits.rst
index 94b6b240a..e190b6c28 100644
--- a/doc/plugins/limits.rst
+++ b/doc/plugins/limits.rst
@@ -2,15 +2,4 @@
Per-admin limits
################
-This plugin offers a way to define limits about how many objects
-(aliases, mailboxes) a domain administrator can create.
-
-It also brings a new administrative role: ``Reseller``. A reseller is a domain
-administrator that can also manipulate domains and assign permissions
-to domain administrators.
-
-If you don't want to limit a particular object type, just set the
-associated value to -1.
-
-Default limits applied to new administrators can be changed through
-the *Modoboa > Parameters > Limits* page.
+`Official documentation `_.
diff --git a/doc/plugins/postfix_autoreply.rst b/doc/plugins/postfix_autoreply.rst
index 0e87414b0..e1683a6b6 100644
--- a/doc/plugins/postfix_autoreply.rst
+++ b/doc/plugins/postfix_autoreply.rst
@@ -4,48 +4,4 @@
Postfix auto-reply messages
###########################
-This plugin let users define an auto-reply message (*vacation*). It is
-based on Postfix capabilities.
-
-The user that executes the autoreply script needs to access
-:file:`settings.py`. You must apply proper permissions on this file. For
-example, if :file:`settings.py` belongs to ``www-data:www-data``, you can add
-the ``vmail`` user to the ``www-data`` group and set the read permission
-for the group.
-
-To make Postfix use this feature, you need to update your
-configuration files as follows:
-
-``/etc/postfix/main.cf``::
-
- transport_maps = :/etc/postfix/sql-autoreplies-transport.cf
- virtual_alias_maps = :/etc/postfix/sql-aliases.cf
- :/etc/postfix/sql-domain-aliases-mailboxes.cf,
- :/etc/postfix/sql-autoreplies.cf,
- :/etc/postfix/sql-catchall-aliases.cf
-
-.. note::
-
- The order used to define alias maps is important, please respect it
-
-``/etc/postfix/master.cf``::
-
- autoreply unix - n n - - pipe
- flags= user=vmail: argv=python /manage.py autoreply $sender $mailbox
-
-Replace ```` by the name of the database you
-use. ```` is the path of your Modoboa instance.
-
-Then, create the requested map files::
-
- $ modoboa-admin.py postfix_maps mapfiles --categories autoreply
-
-`mapfiles` is the directory where the files will be stored. Answer the
-few questions and you're done.
-
-.. note::
-
- Auto-reply messages are just sent one time per sender for a
- pre-defined time period. By default, this period is equal to 1 day
- (86400s), you can adjust this value by modifying the **Automatic
- reply timeout** parameter available in the online panel.
+`Official documentation `_.
diff --git a/doc/plugins/postfix_relay_domains.rst b/doc/plugins/postfix_relay_domains.rst
index 5034f8ef9..7a7c8c7e5 100644
--- a/doc/plugins/postfix_relay_domains.rst
+++ b/doc/plugins/postfix_relay_domains.rst
@@ -2,39 +2,4 @@
Postfix relay domains support
#############################
-This plugin adds the support for relay domains using postfix. You can
-use it when the MTA managed by Modoboa is not the final destination of
-one or several domains.
-
-If activated, two new objects will be available from the *Domains*
-listing page: *relay domain* and *relay domain alias*.
-
-The extension is compatible with the *amavis* and *limits*
-ones. Resellers will be able to create both new objects.
-
-Replace by the name of the database you use.To tell Postfix this feature exists, you must generate two new map
-files and then update your configuration.
-
-To generate the map files, run the following command::
-
- $ modoboa-admin.py postfix_maps --categories relaydomains --dbtype
-
-Replace values between ``<>`` by yours.
-
-Edit the :file:`/etc/postfix/main.cf` file and copy the following
-lines inside::
-
- relay_domains = :/etc/postfix/sql-relaydomains.cf
- transport_maps =
- :/etc/postfix/sql-relaydomains-transport.cf
- :/etc/postfix/sql-relaydomain-aliases-transport.cf
-
- smtpd_recipient_restrictions =
- permit_mynetworks
- reject_unauth_destination
- check_recipient_access
- :/etc/postfix/sql-relay-recipient-verification.cf
-
-Replace ```` by the name of the database you use.
-
-Reload postfix.
+`Official documentation `_.
diff --git a/doc/plugins/radicale.rst b/doc/plugins/radicale.rst
index 511f71aaf..456529d41 100644
--- a/doc/plugins/radicale.rst
+++ b/doc/plugins/radicale.rst
@@ -2,45 +2,4 @@
Radicale frontend
#################
-This plugin provides a simple management frontend for `Radicale
- `_, a complete CalDAV (calendar) and CardDAV
-(contact) server solution.
-
-Features currently supported are:
-
-* Private calendar creation (available for simple users)
-* Rights management for private calendars
-* Shared calendar creation by domain (available for domain administrators)
-
-.. note::
-
- This plugin requires Radicale 0.9 or higher.
-
-Setup
-=====
-
-Once `Radicale is installed
- `_ on your server, you must
-tell Modoboa where it can find the file used to store rules.
-
-Go to the *Modoboa > Parameters > Radicale* panel and fill the
-**Radicale rights file path** setting (an absolute path is required).
-
-When the configuration is done, Modoboa will completly handles the
-file's content. It means every manual modification you could made on
-this file would be overriden.
-
-To do so, a new cron job must be created. You can use the following
-example::
-
- */2 * * * * /manage.py generate_rights
- #
- # Or like this if you use a virtual environment:
- # */2 * * * * /manage.py generate_rights
-
-.. note::
-
- In some cases, the modifications you make on Modoboa may not be
- applied to the rights file. In order to force the generation,
- manually run the ``generate_rights`` command using the ``--force``
- option.
+`Official documentation `_.
diff --git a/doc/plugins/sievefilters.rst b/doc/plugins/sievefilters.rst
index 77f77d2f3..0d714afc9 100644
--- a/doc/plugins/sievefilters.rst
+++ b/doc/plugins/sievefilters.rst
@@ -2,42 +2,4 @@
Sieve filters
#############
-This plugin let users create server-side message filters, using the
-`sievelib module `_ (which
-provides Sieve and ManageSieve clients).
-
-Two working modes are available:
-
-* A raw mode: you create filters using the Sieve language directly
- (advanced users)
-* An assisted mode: you create filters using an intuitive form
-
-To use this plugin, your hosting setup must include a *ManageSieve*
-server and your local delivery agent must understand the *Sieve*
-language. Don't panic, Dovecot supports both :-) (refer to
-:ref:`dovecot` to know how to enable those features).
-
-.. note::
- The sieve filters plugin requires that the :ref:`webmail` plugin is
- activated and configured.
-
-Go the online panel and modify the following parameters in order to
-communicate with the *ManageSieve* server:
-
-+--------------------+--------------------+--------------------+
-|Name |Description |Default value |
-+====================+====================+====================+
-|Server address |Address of your |127.0.0.1 |
-| |MANAGESIEVE server | |
-+--------------------+--------------------+--------------------+
-|Server port |Listening port of |4190 |
-| |your MANAGESIEVE | |
-| |server | |
-+--------------------+--------------------+--------------------+
-|Connect using |Use the STARTTLS |no |
-|STARTTLS |extension | |
-+--------------------+--------------------+--------------------+
-|Authentication |Prefered |auto |
-|mechanism |authentication | |
-| |mechanism | |
-+--------------------+--------------------+--------------------+
+`Official documentation `_.
diff --git a/doc/plugins/statistics.rst b/doc/plugins/statistics.rst
index 57e821747..50fd452b0 100644
--- a/doc/plugins/statistics.rst
+++ b/doc/plugins/statistics.rst
@@ -4,44 +4,4 @@
Graphical statistics
####################
-This plugin collects various statistics about emails traffic on your
-server. It parses a log file to collect information, store it into RRD
-files (see `rrdtool `_) and then
-generates graphics in PNG format.
-
-To use it, go to the online parameters panel and adapt the following
-ones to your environment:
-
-+--------------------+--------------------+--------------------------+
-|Name |Description |Default value |
-+====================+====================+==========================+
-|Path to the log file|Path to log file |/var/log/mail.log |
-| |used to collect | |
-| |statistics | |
-+--------------------+--------------------+--------------------------+
-|Directory to store |Path to directory |/tmp/modoboa |
-|RRD files |where RRD files are | |
-| |stored | |
-+--------------------+--------------------+--------------------------+
-|Directory to store |Path to directory |/media/stats|
-|PNG files |where PNG files are | |
-| |stored | |
-+--------------------+--------------------+--------------------------+
-
-Make sure the directory that will contain RRD files exists. If not,
-create it before going further. For example (according to the previous
-parameters)::
-
- $ mkdir /tmp/modoboa
-
-To finish, you need to collect information periodically in order to
-feed the RRD files. Add the following line into root's crontab::
-
- */5 * * * * /manage.py logparser &> /dev/null
- #
- # Or like this if you use a virtual environment:
- # 0/5 * * * * /manage.py logparser &> /dev/null
-
-Replace ```` with the path of your Modoboa instance.
-
-Graphics will be automatically created after each parsing.
+`Official documentation `_.
diff --git a/doc/plugins/webmail.rst b/doc/plugins/webmail.rst
index 6e5bc8de1..b9df5e984 100644
--- a/doc/plugins/webmail.rst
+++ b/doc/plugins/webmail.rst
@@ -4,68 +4,4 @@
Webmail
#######
-Modoboa provides a simple webmail:
-
-* Browse, read and compose messages, attachments are supported
-* HTML messages are supported
-* `CKeditor `_ integration
-* Manipulate mailboxes (create, move, remove)
-* Quota display
-
-To use it, go to the online panel and modify the following parameters
-to communicate with your *IMAP* server (under *IMAP settings*):
-
-+--------------------+--------------------+--------------------+
-|Name |Description |Default value |
-+====================+====================+====================+
-|Server address |Address of your IMAP|127.0.0.1 |
-| |server | |
-+--------------------+--------------------+--------------------+
-|Use a secured |Use a secured |no |
-|connection |connection to access| |
-| |IMAP server | |
-+--------------------+--------------------+--------------------+
-|Server port |Listening port of |143 |
-| |your IMAP server | |
-+--------------------+--------------------+--------------------+
-
-Do the same to communicate with your SMTP server (under *SMTP settings*):
-
-+--------------------+--------------------+--------------------+
-|Name |Description |Default value |
-+====================+====================+====================+
-|Server address |Address of your SMTP|127.0.0.1 |
-| |server | |
-+--------------------+--------------------+--------------------+
-|Secured connection |Use a secured |None |
-|mode |connection to access| |
-| |SMTP server | |
-+--------------------+--------------------+--------------------+
-|Server port |Listening port of |25 |
-| |your SMTP server | |
-+--------------------+--------------------+--------------------+
-|Authentication |Server needs |no |
-|required |authentication | |
-+--------------------+--------------------+--------------------+
-
-.. note::
-
- The size of each attachment sent with messages is limited. You can
- change the default value by modifying the **Maximum attachment
- size** parameter.
-
-Using CKeditor
-==============
-
-Modoboa supports CKeditor to compose HTML messages. To use it, first
-download it from `the official website `_, then
-extract the tarball::
-
- $ cd
- $ tar xzf /path/to/ckeditor/tarball.tag.gz -C sitestatic/js/
-
-And you're done!
-
-Now, each user has the possibility to choose between CKeditor and the
-raw text editor to compose their messages. (see *User > Settings >
-Preferences > Webmail*)
+`Official documentation `_.
From 8b2768bc1abba6c25b2d8b80bdfe692240b4cd85 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Sun, 5 Apr 2015 14:47:52 +0200
Subject: [PATCH 19/25] Fix unit tests.
---
modoboa/core/tests.py | 68 +--------------------------------------
modoboa/lib/test_utils.py | 45 ++++++++++++++++++++++++++
2 files changed, 46 insertions(+), 67 deletions(-)
diff --git a/modoboa/core/tests.py b/modoboa/core/tests.py
index 13e983c17..ee070a693 100644
--- a/modoboa/core/tests.py
+++ b/modoboa/core/tests.py
@@ -1,16 +1,12 @@
-import os
-import tempfile
+"""Tests for core application."""
from django.core.urlresolvers import reverse
-from django.test import TestCase
-from modoboa.lib.sysutils import exec_cmd
from modoboa.lib.tests import ModoTestCase
from . import factories
class ProfileTestCase(ModoTestCase):
- fixtures = ['initial_users.json']
def setUp(self):
super(ProfileTestCase, self).setUp()
@@ -46,65 +42,3 @@ class ProfileTestCase(ModoTestCase):
self.assertTrue(
self.clt.login(username="user@test.com", password="tutu")
)
-
-
-class ModoboaAdminCommandTestCase(TestCase):
-
- MAP_FILES = {
- "modoboa_admin": [
- "sql-domains.cf", "sql-domain-aliases.cf", "sql-aliases.cf",
- "sql-domain-aliases-mailboxes.cf", "sql-catchall-aliases.cf",
- "sql-maintain.cf"
- ],
- "modoboa_postfix_autoreply": [
- "sql-autoreplies-transport.cf", "sql-autoreplies.cf"
- ],
- "modoboa_admin_relaydomains": [
- "sql-relaydomains.cf", "sql-relaydomains-transport.cf",
- "sql-relaydomain-aliases-transport.cf",
- "sql-relay-recipient-verification.cf"
- ]
- }
-
- def setUp(self):
- self.workdir = tempfile.mkdtemp()
-
- def tearDown(self):
- exec_cmd("rm -rf {0}".format(self.workdir))
-
- def _test_maps_generation(self, engine, extensions=None):
- if extensions is None:
- extensions = [
- "modoboa_admin", "modoboa_postfix_autoreply",
- "modoboa_admin_relaydomains"
- ]
- dburl = "{0}://user:password@localhost/testdb".format(engine)
- code, output = exec_cmd(
- "modoboa-admin.py postfix_maps --extensions {0}"
- " --dburl {1} {2}".format(
- " ".join(extensions), dburl, self.workdir
- )
- )
- self.assertEqual(code, 0)
- for extension in extensions:
- for mapfile in self.MAP_FILES[extension]:
- path = "{0}/{1}".format(self.workdir, mapfile)
- self.assertTrue(os.path.exists(path))
- with open(path) as fpo:
- content = fpo.read()
- if engine != "sqlite":
- self.assertIn("user = user", content)
- self.assertIn("password = password", content)
- self.assertIn("dbname = testdb", content)
- self.assertIn("hosts = localhost", content)
- else:
- self.assertIn("dbpath = testdb", content)
-
- def test_postgres_maps(self):
- self._test_maps_generation("postgres")
-
- def test_mysql_maps(self):
- self._test_maps_generation("mysql")
-
- def test_sqlite_maps(self):
- self._test_maps_generation("sqlite")
diff --git a/modoboa/lib/test_utils.py b/modoboa/lib/test_utils.py
index 98888069e..e731d2522 100644
--- a/modoboa/lib/test_utils.py
+++ b/modoboa/lib/test_utils.py
@@ -3,6 +3,8 @@
import os
import tempfile
+from django.test import TestCase
+
from .sysutils import exec_cmd
@@ -41,3 +43,46 @@ class TestRunnerMixin(object):
self.assertEqual(code, 0)
+class MapFilesTestCase(TestCase):
+
+ """A generic test case to check map files generation."""
+
+ MAP_FILES = None
+
+ def setUp(self):
+ self.workdir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ exec_cmd("rm -rf {0}".format(self.workdir))
+
+ def _test_maps_generation(self, engine):
+ dburl = "{0}://user:password@localhost/testdb".format(engine)
+ code, output = exec_cmd(
+ "modoboa-admin.py postfix_maps --extensions {0}"
+ " --dburl {1} {2}".format(
+ self.extension, dburl, self.workdir
+ )
+ )
+ self.assertEqual(code, 0)
+
+ for mapfile in self.MAP_FILES:
+ path = "{0}/{1}".format(self.workdir, mapfile)
+ self.assertTrue(os.path.exists(path))
+ with open(path) as fpo:
+ content = fpo.read()
+ if engine != "sqlite":
+ self.assertIn("user = user", content)
+ self.assertIn("password = password", content)
+ self.assertIn("dbname = testdb", content)
+ self.assertIn("hosts = localhost", content)
+ else:
+ self.assertIn("dbpath = testdb", content)
+
+ def test_postgres_maps(self):
+ self._test_maps_generation("postgres")
+
+ def test_mysql_maps(self):
+ self._test_maps_generation("mysql")
+
+ def test_sqlite_maps(self):
+ self._test_maps_generation("sqlite")
From d11c8265ba28a34f85eefd04ce1db88357f2567e Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Sun, 5 Apr 2015 14:58:42 +0200
Subject: [PATCH 20/25] Fix unit tests.
---
modoboa/lib/test_utils.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/modoboa/lib/test_utils.py b/modoboa/lib/test_utils.py
index e731d2522..66b759056 100644
--- a/modoboa/lib/test_utils.py
+++ b/modoboa/lib/test_utils.py
@@ -3,8 +3,6 @@
import os
import tempfile
-from django.test import TestCase
-
from .sysutils import exec_cmd
@@ -43,12 +41,14 @@ class TestRunnerMixin(object):
self.assertEqual(code, 0)
-class MapFilesTestCase(TestCase):
+class MapFilesTestCaseMixin(object):
"""A generic test case to check map files generation."""
MAP_FILES = None
+ extension = None
+
def setUp(self):
self.workdir = tempfile.mkdtemp()
From c5040c5902e0baecb03c7cd8b949b0c35defceb7 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 8 Apr 2015 15:58:06 +0200
Subject: [PATCH 21/25] Documentation updated.
---
doc/conf.py | 4 +-
doc/getting_started/install.rst | 48 ++++++++++++-----------
doc/getting_started/upgrade.rst | 63 +++++++++++++++++++++++++++++--
doc/integration/imap_and_smtp.rst | 4 +-
4 files changed, 90 insertions(+), 29 deletions(-)
diff --git a/doc/conf.py b/doc/conf.py
index 741a149d7..88bf64a2e 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -50,9 +50,9 @@ copyright = u'2015, Antoine Nguyen'
# built documents.
#
# The short X.Y version.
-version = '1.2'
+version = '1.3'
# The full version, including alpha/beta/rc tags.
-release = '1.2.1'
+release = '1.3.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/doc/getting_started/install.rst b/doc/getting_started/install.rst
index 611cf84ca..bdd09dbee 100644
--- a/doc/getting_started/install.rst
+++ b/doc/getting_started/install.rst
@@ -93,37 +93,31 @@ Deployment
`modoboa-admin.py`, a command line tool, lets you deploy a
*ready-to-use* Modoboa site using only one instruction::
- $ modoboa-admin.py deploy modoboa_example --collectstatic [--with-amavis] [--dburl database-url] [--amavis_dburl database-url]
-
-Just answer the few questions and you're done. You can now go to the
-:ref:`first_use` section.
+ $ modoboa-admin.py deploy modoboa_example --collectstatic [--dburl default:database-url] [--extensions extensions]
.. note::
- The `--with-amavis` option must be set only if you intend to use
- the :ref:`amavis_frontend`.
-
-In case you need a **silent installation** (e.g. if you're using
-Salt-Stack, Ansible or whatever), it's possible to supply the database
-credentials as commandline arguments.
-
-You can see the complete option list by running the following command::
-
- $ modoboa-admin.py help deploy
+ By default, only the core application of Modoboa is installed. To
+ install extensions, use the ``--extensions`` option which accepts a
+ list of extension names as argument (``--extensions ext1 ext2 ...``).
+ If you want to use install all extensions, just use the ``all``
+ shortcut like this ``--extensions all``.
.. note::
- `--dburl database-url` for the modoboa database credentials
- `--amavis_dburl database-url` for the amavis database credentials
+ You can specify more than one database connection using the
+ ``--dburl`` option. Multiple connections are differentiated by a
+ prefix. The primary connection must use the ``default:`` prefix (as
+ shown in the example above). For the `amavis extension
+ `_ extension, use the
+ ``amavis:`` prefix like this ``--dburl amavis:``.
- Your database-url should meet the following syntax:
- ``scheme://[user:pass@][host:port]/dbname``
+ Your database url should meet the following syntax
+ ``scheme://[user:pass@][host:port]/dbname`` **OR**
+ ``sqlite:////full/path/to/your/database/file.sqlite``.
- **or**
+ Available schemes are:
- ``sqlite:////full/path/to/your/database/file.sqlite``
-
- Available `schemes` are:
* postgres
* postgresql
* postgis
@@ -131,6 +125,16 @@ You can see the complete option list by running the following command::
* mysql2
* sqlite
+The command will ask you a few questions, answer them and you're
+done. You can now go to the :ref:`first_use` section.
+
+In case you need a **silent installation** (e.g. if you're using
+Salt-Stack, Ansible or whatever), it's possible to supply the database
+credentials as commandline arguments.
+
+You can see the complete option list by running the following command::
+
+ $ modoboa-admin.py help deploy
.. note::
diff --git a/doc/getting_started/upgrade.rst b/doc/getting_started/upgrade.rst
index eacf67fce..f773c1224 100644
--- a/doc/getting_started/upgrade.rst
+++ b/doc/getting_started/upgrade.rst
@@ -33,9 +33,8 @@ your instance was first deployed::
If you customized your configuration file (:file:`settings.py`) with
non-standard settings, you'll have to re-apply them.
-Then, run ``modoboa-admin.py deploy``::
-
- $ modoboa-admin.py deploy --collectstatic [--with-amavis] [--dburl database-url] [--amavis_dburl database-url] [--domain hostname] [--lang lang] [--timezone timezone]
+Finally, run the ``deploy`` comamand. Make sure to consult the
+:ref:`deployment` section to know more about the available options.
If you prefer the manual way, check if
:ref:`specific_upgrade_instructions` are required according to the
@@ -50,6 +49,64 @@ you did choose. See :ref:`webservers` for more details.
Specific upgrade instructions
*****************************
+1.3.0
+=====
+
+This release does not bring awesome new features but it is a necessary
+bridge to the future of Modoboa. All extensions now have their own git
+repository and the deploy process has been updated to reflect this
+change.
+
+Another important update is the use of Django 1.7. Besides its new
+features, the migration system has been reworked and is now more
+robust than before.
+
+Before we begin with the procedure, here is a table showing old
+extension names and their new name:
+
++----------------------------------------+--------------------------+--------------------------+
+|Old name |New package name |New module name |
++========================================+==========================+==========================+
+|modoboa.extensions.admin |modoboa-admin |modoboa_admin |
++----------------------------------------+--------------------------+--------------------------+
+|modoboa.extensions.limits |modoboa-admin-limits |modoboa_admin_limits |
++----------------------------------------+--------------------------+--------------------------+
+|modoboa.extensions.postfix_autoreply |modoboa-postfix-autoreply |modoboa_postfix_autoreply |
++----------------------------------------+--------------------------+--------------------------+
+|modoboa.extensions.postfix_relay_domains|modoboa-admin-relaydomains|modoboa_admin_relaydomains|
++----------------------------------------+--------------------------+--------------------------+
+|modoboa.extensions.radicale |modoboa-radicale |modoboa_radicale |
++----------------------------------------+--------------------------+--------------------------+
+|modoboa.extensions.sievefilters |modoboa-sievefilters |modoboa_sievefilters |
++----------------------------------------+--------------------------+--------------------------+
+|modoboa.extensions.stats |modoboa-stats |modoboa_stats |
++----------------------------------------+--------------------------+--------------------------+
+|modoboa.extensions.webmail |modoboa-webmail |modoboa_webmail |
++----------------------------------------+--------------------------+--------------------------+
+
+Here are the required steps:
+
+#. Install the extensions using pip (look at the second column in the table above)::
+
+ $ pip install
+
+#. Remove ``south`` from ``INSTALLED_APPS``
+
+#. Rename old extension names inside ``MODOBOA_APPS`` (look at the third column in the table above)
+
+#. Remove ``modoboa.lib.middleware.ExtControlMiddleware`` from ``MIDDLEWARE_CLASSES``
+
+#. Change ``DATABASE_ROUTERS`` to::
+
+ DATABASE_ROUTERS = ["modoboa_amavis.dbrouter.AmavisRouter"]
+
+#. Run the following commands::
+
+ $ cd
+ $ python manage.py migrate
+ $ python manage.py load_initial_data
+ $ python manage.py collectstatic
+
1.2.0
=====
diff --git a/doc/integration/imap_and_smtp.rst b/doc/integration/imap_and_smtp.rst
index d14f413bd..cfcd02ab4 100644
--- a/doc/integration/imap_and_smtp.rst
+++ b/doc/integration/imap_and_smtp.rst
@@ -422,9 +422,9 @@ be used by Postfix to lookup into Modoboa tables.
To automaticaly generate the requested map files and store them in a
directory, run the following command::
- $ modoboa-admin.py postfix_maps --dbtype mapfiles
+ $ modoboa-admin.py postfix_maps --dbtype --extensions
-:file:`mapfiles` is the directory where the files will be
+```` is the directory where the files will be
stored. Answer the few questions and you're done.
.. _postfix_config:
From 8b4913a566e9b3228793c7c3b5f4cc5ed76fdcb3 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 8 Apr 2015 16:00:16 +0200
Subject: [PATCH 22/25] Translation files updated
---
modoboa/locale/cs_CZ/LC_MESSAGES/django.po | 307 +++++++++++----
modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po | 9 +-
modoboa/locale/de/LC_MESSAGES/django.po | 311 +++++++++++----
modoboa/locale/de/LC_MESSAGES/djangojs.po | 9 +-
modoboa/locale/en/LC_MESSAGES/django.po | 259 ++++++++++---
modoboa/locale/en/LC_MESSAGES/djangojs.po | 9 +-
modoboa/locale/es/LC_MESSAGES/django.po | 375 +++++++++++--------
modoboa/locale/es/LC_MESSAGES/djangojs.po | 11 +-
modoboa/locale/fr/LC_MESSAGES/django.po | 310 +++++++++++----
modoboa/locale/fr/LC_MESSAGES/djangojs.po | 9 +-
modoboa/locale/it/LC_MESSAGES/django.po | 324 +++++++++++-----
modoboa/locale/it/LC_MESSAGES/djangojs.po | 11 +-
modoboa/locale/nl_NL/LC_MESSAGES/django.po | 308 +++++++++++----
modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po | 9 +-
modoboa/locale/pt_BR/LC_MESSAGES/django.po | 310 +++++++++++----
modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po | 9 +-
modoboa/locale/pt_PT/LC_MESSAGES/django.po | 292 ++++++++++++---
modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po | 9 +-
modoboa/locale/ru/LC_MESSAGES/django.po | 323 +++++++++++-----
modoboa/locale/ru/LC_MESSAGES/djangojs.po | 11 +-
modoboa/locale/sv/LC_MESSAGES/django.po | 309 +++++++++++----
modoboa/locale/sv/LC_MESSAGES/djangojs.po | 9 +-
22 files changed, 2665 insertions(+), 868 deletions(-)
diff --git a/modoboa/locale/cs_CZ/LC_MESSAGES/django.po b/modoboa/locale/cs_CZ/LC_MESSAGES/django.po
index fa2d049bb..5dc47ee79 100644
--- a/modoboa/locale/cs_CZ/LC_MESSAGES/django.po
+++ b/modoboa/locale/cs_CZ/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2015-01-06 10:05+0000\n"
"Last-Translator: Miroslav Abrahám \n"
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/"
@@ -18,48 +18,65 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Obecné"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr "Nové verze Modoboa je k dispozici"
+
+#: core/__init__.py:85
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available"
+msgstr "Je dostupná aktualizace!"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Ověření"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Typ ověření"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Lokální"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Rozhraní pro ověřování přístupu"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Výchozí schéma hesel"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (slabé)"
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (slabé)"
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (slabé)"
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (slabé)"
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "žádné (slabé)"
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Použité schéma pro šifrování hesel schránek"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr "Počet cyklů"
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
@@ -67,48 +84,63 @@ msgid ""
msgstr ""
"Počet cyklů (použije se pouze u sha256crypt a sha512crypt). Hodnota musí být "
"mezi 1000 a 999999999 včetně."
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Tajný klíč"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Klíč používaný k šifrování/dešifrování hesel"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Nastavení LDAP"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Adresa serveru"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "IP adresa DNS jména LDAP serveru"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Port serveru"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Port TCP, který používá LDAP server"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Použít zabezpečené připojení"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Použít připojení SSL/TLS pro přístup k LDAP serveru"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Metoda ověření"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Vyhledat a spojit"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Přímé spojení"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Zvolte si metodu ověření, která se použije"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Spojení pomocí DN"
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -116,23 +148,29 @@ msgid ""
msgstr ""
"Rozlišovací jméno, které se použije při spojování s LDAP serverem. "
"Ponechejte prázdné pro anonymní spojení."
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Heslo spojení"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"Heslo, které se použije při spojování s LDAP serverem (při výběru DN "
"spojení)."
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr "Základna struktury uživatelů"
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "Rozlišovací jméno základny struktury používané pro hledání uživatelů"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Vyhledávací filtr"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -140,9 +178,11 @@ msgid ""
msgstr ""
"Volitelný filtr (např. '(objectClass=osoba)'). Aby byl filtr platný, je "
"nezbytné jen uzavřít do závorek."
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Šablona uživatelského DN"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -151,22 +191,28 @@ msgid ""
msgstr ""
"Šablona použitá pro tvorbu uživatelského rozlišovacího jména (DN). Měla by "
"obsahovat jeden zástupný řetězec (tj. %(user)s)."
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Atribut hesla"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Atribut používaný pro ukládání hesel uživatelů"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr ""
"Volba určující, jestli je nebo není LDAP server serverem Active Directory"
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Správcovské skupiny"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
@@ -174,268 +220,346 @@ msgid ""
msgstr ""
"Členové těchto LDAP Posix skupin budou automaticky vytvořeni jako správci "
"domény. Pro oddělení skupin použijte ';'."
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Základna struktury skupin"
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "Rozlišovací jméno základny struktury používané pro hledání skupin"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Různé"
+
#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Interval aktualizací upozornění"
+
#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Interval mezi aktualizacemi upozornění na stránce"
+
#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Zkontrolovat verzi"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Automaticky kontrolovat dostupnost nové verze"
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Maximální stáří záznamu"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "Maximální stáří záznamu ve dnech"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Položek na stránce"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Počet zobrazených položek na stránce"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Výchozí přesměrování aplikace"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"Výchozí přesměrování, které se použije, pokud není žádná aplikace "
"specifikována"
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Klíč musí mít délku 16, 24 nebo 32 znaků"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Neplatná syntaxe"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Neplatný počet cyklů"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Toto pole je vyžadováno"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Zobrazení"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Preferovaný jazyk"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Preferovaný jazyk pro zobrazení stránek"
+
#: core/forms.py:14
msgid "Username"
msgstr "Uživatelské jméno"
+
#: core/forms.py:18
msgid "Password"
msgstr "Heslo"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Původní heslo"
+
#: core/forms.py:33
msgid "New password"
msgstr "Nové heslo"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Potvrzení"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Původní heslo se neshoduje"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Hesla se neshodují"
+
#: core/models.py:52
msgid "password"
msgstr "heslo"
+
#: core/models.py:54
msgid "last login"
msgstr "poslední přihlášení"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Nemůžete smazat vlastní účet"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Nebylo možné změnit heslo: LDAP modul není instalován"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "účet"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Neplatný řádek"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "Nemůžete importvat účet s vyšším oprávněním, než máte vy sám"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "Běžný uživatel '%s' musí mít nastavenou platnou emailovou adresu"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "pole uživatelského jména a emailu se nesmí pro '%s' lišit"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "přidáno"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "upraveno"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s uživatelem %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "smazáno"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Rozšíření"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Zvolte rozšíření, která chcete použít"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Jméno"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Verze"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Popis"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Informace"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Různé informace o Modoboa"
+
#: core/templates/core/information.html:5
-msgid "An update is available!"
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "Je dostupná aktualizace!"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-"\n"
-"Modoboa %(version)s je dostupná ke stažení. Seznam všech "
-"změn je k dispozici zde ."
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "se aktuálně používá."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Ověření"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Jméno"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Poslední přihlášení"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Popis"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Aktivní uživatelé"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Název skupiny"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Poslední přihlášení"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Záznamy"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Dříve v Modoboa..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Datum"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Úroveň"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Zaznamenal"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Zpráva"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Parametry"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Nastavit Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Uložit"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Nastavení Modoboa"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Nastavení"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Možnosti"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Nastavit Modoboa"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Profil"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Aktualizovat osobní informace"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Aktualizovat"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Odhlásit se"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Vítejte v Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Parametry uloženy"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Uživatel '%s' se úspěšně přihlásil"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Vaše uživatelské jméno nebo heslo se neshodují. Zkuste to prosím znovu."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Uživatel '%s' se odhlásil"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profil aktualizován"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Možnosti uloženy"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Testovací zprávy"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Poslat vir"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Poslat spam"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -466,93 +590,150 @@ msgstr ""
"Nahlašte prosím jakékoli objevené problémy nebo vaše návrhy přes\n"
" emailový "
"seznam .
\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Zpráva odeslána"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Připojení k databázi %s není nastaveno"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Přístup zamítnut: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Přístup zamítnut"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr "Uložit"
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Neplatný požadavek"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Vložte platné doménové jméno"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Ano"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "Ne"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Nebylo možné změnit heslo: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Bežný uživatel"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super správce"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Správce domény"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Omlouváme se"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "Požadovaná stránka neexistuje."
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Objevila se interní chyba."
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Hledat..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Z adresy"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Předmět"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Obojí"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Chyba:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Nápověda:"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Zavřít"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Předchozí"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Další"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Vítejte v Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Zapamatovat si"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Přihlásit"
+
+#~ msgid "New Modoboa version available"
+#~ msgstr "Nové verze Modoboa je k dispozici"
+
+#~ msgid "Extensions"
+#~ msgstr "Rozšíření"
+
+#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Zvolte rozšíření, která chcete použít"
+
+#~ msgid "Version"
+#~ msgstr "Verze"
+
+#~ msgid ""
+#~ "\n"
+#~ " Modoboa %(version)s is available for download. The "
+#~ "list of all changes is available here .\n"
+#~ " "
+#~ msgstr ""
+#~ "\n"
+#~ "Modoboa %(version)s je dostupná ke stažení. Seznam všech "
+#~ "změn je k dispozici zde"
+#~ "a>."
+
+#~ msgid "is currently in use."
+#~ msgstr "se aktuálně používá."
diff --git a/modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po b/modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po
index 85ff875e0..ac3987437 100644
--- a/modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/cs_CZ/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2015-01-06 10:05+0000\n"
"Last-Translator: Miroslav Abrahám \n"
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/"
@@ -18,24 +18,31 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Žádný další záznam logu k zobrazení"
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Upozornění"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Zrušit"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr "Interní chyba"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Žádná další informace k zobrazení"
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Hledat"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Hledat..."
diff --git a/modoboa/locale/de/LC_MESSAGES/django.po b/modoboa/locale/de/LC_MESSAGES/django.po
index 35328b0d0..553424e63 100644
--- a/modoboa/locale/de/LC_MESSAGES/django.po
+++ b/modoboa/locale/de/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2014-12-03 11:02+0000\n"
"Last-Translator: Arvedui \n"
"Language-Team: German (http://www.transifex.com/projects/p/modoboa/language/"
@@ -19,48 +19,65 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Grundsätzlich"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr "Neue Modoboa Version verfügbar"
+
+#: core/__init__.py:85
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available"
+msgstr "Ein Update ist Verfügbar!"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Authentifizierung"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Authentifizierungstyp"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Lokal"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Das backend, das zur Authentifizierung genutzt wird"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Standard Passwortschema"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (schwach)"
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (schwach)"
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (schwach)"
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (schwach)"
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (schwach)"
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Verschlüsselungsschema der Mailbox-Passworte"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr "Runden"
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
@@ -68,69 +85,90 @@ msgid ""
msgstr ""
"Anzahl zu verwendender Runden (nur für sha256crypt und sha512crypt). Zahl "
"muss zwischen 1000 und 999999999 liegen."
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Geheimer Schlüssel"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Verwendeter Schlüssel, um Passworte zu ver-/entschlüsseln"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "LDAP-Einstellungen"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Server-Adresse"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "Die IP-Adresse des LDAP-Server Hostnamens"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Server-Port"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Der TCP Port des LDAP-Servers"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Gesicherte Verbindung verwenden"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "SSL/TLS-Verbindung für Zugriff auf LDAP-Server verwenden"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Authentifizierungsmethode"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Suchen und Bind anwenden"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Direkter Bind"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Wählen Sie die Authentifizierungsmethode aus"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Bind DN"
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
msgstr ""
"Der DN für einen Bind an den LDAP-Server. Nichts eingeben für anonymen Bind."
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Bind Passwort"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr "Das Kennwort wenn mit dem Bind DN angemeldet wird."
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr "Anwender Search Base"
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "Der DN der Search Base mit der Anwenderkonten gefunden werden"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Suchfilter"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -138,9 +176,11 @@ msgid ""
msgstr ""
"Ein optionaler Filter z.B. (objectClass=person). Das Filter muss "
"entsprechend der LDAP-Konvention in Klammern gesetzt werden."
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Vorlage für User DN"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -149,21 +189,27 @@ msgid ""
msgstr ""
"Die Vorlage für einen User DN. Sie sollte einen Platzhalter z.B. %(user)s "
"enthalten."
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Passwort-Attribut"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Das Attribut für Benutzerpassworte"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Auswählen wenn der LDAP-Server ein Active Directory ist."
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Administrator-Gruppen"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
@@ -171,270 +217,347 @@ msgid ""
msgstr ""
"Mitglieder dieser LDAP Posix-Gruppe werden als Domain-Administratoren "
"angelegt werden. Nutzen sie ';', um Gruppen zu separieren."
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Gruppen Search Base"
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "Der DN der Search Base mit Gruppen gefunden werden"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Verschiedenes"
+
#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Benachrichtigungs Prüfintervall"
+
#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Prüfintervall nach neuen Benachrichtigungen"
+
#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Überprüfe auf neue Versionen"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Überprüft automatisch ob eine neuere Version verfügbar ist."
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Maximales Alter eines Log-Eintrags"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "Das maximale Alter eines Log-Eintrags (in Tagen)"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Einträge pro Seite"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Anzahl dargestellter Einträge pro Seite"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Standard Top-Redirect"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr "Die Standardumleitung wenn kein Programm angegeben wurde"
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Schlüssel muss 16, 24 oder 32 Byte lang sein"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Ungültige Syntax"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Ungültige Zahl für Runden"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Dieses Feld ist erforderlich"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Darstellung"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Bevorzugte Sprache"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Bevorzugte Sprache für Seitendarstellung"
+
#: core/forms.py:14
msgid "Username"
msgstr "Benutzername"
+
#: core/forms.py:18
msgid "Password"
msgstr "Passwort"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Altes Passwort"
+
#: core/forms.py:33
msgid "New password"
msgstr "Neues Passwort"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Bestätigung"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Altes Passwort stimmt nicht überein"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Passwörter stimmen nicht überein"
+
#: core/models.py:52
msgid "password"
msgstr "Passwort"
+
#: core/models.py:54
msgid "last login"
msgstr "Letzte Anmeldung"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Sie können Ihr eigenes Konto nicht entfernen"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Konnte Kennwort nicht aktualisieren: LDAP-Modul nicht installiert"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "Konto"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Ungültige Zeile"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "Sie können kein Konto einer höheren Rolle importieren"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "Der normale Benutzer '%s' muss eine gültige E-Mail-Adresse besitzen"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr ""
"Die Felder für Benutzername und E-Mail für '%s' dürfen sich nicht "
"unterscheiden"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "hinzugefügt"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "verändert"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s der Identität %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "entfernt"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Erweiterungen"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Extension auswählen"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Name"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Version"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Beschreibung"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Information"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Verschiedene Informationen über Modoboa"
+
#: core/templates/core/information.html:5
-msgid "An update is available!"
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "Ein Update ist Verfügbar!"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-"\n"
-"Modoboa %(version)s steht zum Download bereit. Die liste "
-"der Änderungen ist hier "
-"verfügbar."
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "ist momentan in Gebrauch."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Authentifizierung"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Name"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Letzte Anmeldung"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Beschreibung"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Aktive Benutzer"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Gruppenname"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Letzte Anmeldung"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Logs"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Vorher auf Modoboa…"
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Datum"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Level"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Nachricht"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Parameter"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Modoboa konfigurieren"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Speichern"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Modoboa-Einstellungen"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Einstellungen"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Einstellungen"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Modoboa anpassen"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Profil"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Aktualisieren sie ihre persönlichen Daten"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Aktualisieren"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Logout"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Willkommen zu Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Parameter gespeichert"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Identität '%s' hat sich erfolgreich angemeldet"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Ihr Benutzername und Passwort stimmen nicht überein. Bitte versuchen Sie es "
"noch einmal."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Identität '%s' hat sich abgemeldet"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profil aktualisiert"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Einstellungen gespeichert"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Test-Nachrichten"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Virus senden"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Spam senden"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -465,98 +588,150 @@ msgstr ""
"Probleme und Anregungen bitte an die\n"
" Mailingliste berichten.
\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Nachricht gesendet"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Verbindung zu Datenbank %s nicht konfiguriert"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Erlaubnis verweigert: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Berechtigung verweigert"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr "Abschicken"
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Ungültige Anfrage"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Geben Sie einen gültigen Domain-Namen an"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Ja"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "Nein"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Konnte Kennwort nicht aktualisieren: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Normaler Anwender"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super-Administrator"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Domänen-Administrator"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Entschuldigung"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "Die angeforderte Seite existiert nicht"
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Ein interne Fehler ist aufgetreten"
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Suchen..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "From:-Adresse"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Betreff"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Beide"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Fehler:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Hilfe:"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Schliessen"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Vorheriges"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Nächstes"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Willkommen zu Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Erinnere mich"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Anmelden"
+
+#~ msgid "New Modoboa version available"
+#~ msgstr "Neue Modoboa Version verfügbar"
+
+#~ msgid "Extensions"
+#~ msgstr "Erweiterungen"
+
#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Extension auswählen"
+
+#~ msgid "Version"
+#~ msgstr "Version"
+
+#~ msgid ""
+#~ "\n"
+#~ " Modoboa %(version)s is available for download. The "
+#~ "list of all changes is available here .\n"
+#~ " "
+#~ msgstr ""
+#~ "\n"
+#~ "Modoboa %(version)s steht zum Download bereit. Die liste "
+#~ "der Änderungen ist hier"
+#~ "a> verfügbar."
+
+#~ msgid "is currently in use."
+#~ msgstr "ist momentan in Gebrauch."
diff --git a/modoboa/locale/de/LC_MESSAGES/djangojs.po b/modoboa/locale/de/LC_MESSAGES/djangojs.po
index bb99e0e0e..68d5310d5 100644
--- a/modoboa/locale/de/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/de/LC_MESSAGES/djangojs.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2014-12-01 12:12+0000\n"
"Last-Translator: Arvedui \n"
"Language-Team: German (http://www.transifex.com/projects/p/modoboa/language/"
@@ -19,24 +19,31 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Keine weiteren log eintrage"
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Warnung"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Abbrechen"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr "Interner Fehler"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Keine weiteren Einträge"
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Suche"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Suchen..."
diff --git a/modoboa/locale/en/LC_MESSAGES/django.po b/modoboa/locale/en/LC_MESSAGES/django.po
index 4419e2e77..269282dcb 100644
--- a/modoboa/locale/en/LC_MESSAGES/django.po
+++ b/modoboa/locale/en/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -16,403 +16,522 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr ""
-#: core/__init__.py:84
-msgid "New Modoboa version available"
+
+#: core/__init__.py:85
+msgid "One or more updates are available"
msgstr ""
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr ""
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr ""
+
#: core/app_settings.py:38
msgid "Local"
msgstr ""
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr ""
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr ""
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr ""
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr ""
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr ""
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr ""
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr ""
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr ""
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr ""
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr ""
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr ""
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr ""
+
#: core/app_settings.py:80
msgid "Server address"
msgstr ""
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr ""
+
#: core/app_settings.py:88
msgid "Server port"
msgstr ""
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr ""
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr ""
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr ""
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr ""
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr ""
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr ""
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr ""
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr ""
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
"for an anonymous bind"
msgstr ""
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr ""
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr ""
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr ""
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr ""
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
"valid, it must be enclosed in parentheses."
msgstr ""
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr ""
+
#: core/app_settings.py:158
#, python-format
msgid ""
"The template used to construct a user's DN. It should contain one "
"placeholder (ie. %(user)s)"
msgstr ""
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr ""
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr ""
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr ""
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr ""
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr ""
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
msgstr ""
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr ""
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr ""
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr ""
+
#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr ""
+
#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr ""
+
#: core/app_settings.py:208
msgid "Check new versions"
msgstr ""
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr ""
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr ""
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr ""
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr ""
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr ""
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr ""
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr ""
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr ""
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr ""
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr ""
+
#: core/app_settings.py:367
msgid "Display"
msgstr ""
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr ""
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr ""
+
#: core/forms.py:14
msgid "Username"
msgstr ""
+
#: core/forms.py:18
msgid "Password"
msgstr ""
+
#: core/forms.py:29
msgid "Old password"
msgstr ""
+
#: core/forms.py:33
msgid "New password"
msgstr ""
+
#: core/forms.py:37
msgid "Confirmation"
msgstr ""
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr ""
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr ""
+
#: core/models.py:52
msgid "password"
msgstr ""
+
#: core/models.py:54
msgid "last login"
msgstr ""
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr ""
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr ""
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr ""
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr ""
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr ""
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr ""
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr ""
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr ""
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr ""
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr ""
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr ""
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr ""
-#: core/templates/core/extensions.html:4
-msgid "The extension(s) you are using"
-msgstr ""
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr ""
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr ""
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr ""
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr ""
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr ""
+
#: core/templates/core/information.html:5
-msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr ""
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-#: core/templates/core/information.html:11
-msgid "is currently in use."
+
+#: core/templates/core/information.html:10
+msgid "Applications"
msgstr ""
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr ""
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+msgid "Last version"
+msgstr ""
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr ""
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr ""
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr ""
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr ""
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr ""
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr ""
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr ""
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr ""
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr ""
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr ""
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr ""
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr ""
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr ""
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr ""
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr ""
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr ""
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr ""
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr ""
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr ""
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr ""
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr ""
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr ""
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+msgid "The core part of Modoboa"
+msgstr ""
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr ""
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr ""
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr ""
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr ""
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr ""
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr ""
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr ""
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr ""
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -429,93 +548,121 @@ msgid ""
" the "
"mailing list .\n"
msgstr ""
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr ""
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr ""
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr ""
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr ""
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr ""
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr ""
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr ""
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr ""
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr ""
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr ""
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr ""
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr ""
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr ""
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr ""
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr ""
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr ""
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr ""
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr ""
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr ""
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr ""
+
#: templates/common/error.html:4
msgid "Error:"
msgstr ""
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr ""
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr ""
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr ""
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr ""
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr ""
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr ""
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr ""
diff --git a/modoboa/locale/en/LC_MESSAGES/djangojs.po b/modoboa/locale/en/LC_MESSAGES/djangojs.po
index cfcd3c47e..118bf6b05 100644
--- a/modoboa/locale/en/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/en/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -16,24 +16,31 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr ""
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr ""
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr ""
+
#: static/js/global.js:329
msgid "Internal error"
msgstr ""
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr ""
+
#: static/js/listing.js:46
msgid "Search"
msgstr ""
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr ""
diff --git a/modoboa/locale/es/LC_MESSAGES/django.po b/modoboa/locale/es/LC_MESSAGES/django.po
index c639410e3..c7f3fd6e6 100644
--- a/modoboa/locale/es/LC_MESSAGES/django.po
+++ b/modoboa/locale/es/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2013-10-01 09:56+0000\n"
"Last-Translator: Pedro Gracia \n"
"Language-Team: Spanish (http://www.transifex.com/projects/p/modoboa/language/"
@@ -19,95 +19,126 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "General"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr ""
+
+#: core/__init__.py:85
+#, fuzzy
+msgid "One or more updates are available"
+msgstr "No hay estadísticas disponibles"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autenticación"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Tipo de autenticación"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Local"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "El sistema usado para autenticación"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Esquema de contraseña por defecto"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr ""
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr ""
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr ""
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr ""
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr ""
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Esquema usado para cifrar las contraseñas del mailbox"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr ""
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Clave secreta"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Clave usada para cifrar/descifrar contraseñas"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Configuración de LDAP"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Dirección del servidor"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "La dirección IP del servidor de nombres (DNS) del servidor LDAP"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Puerto del servidor"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Número de puerto TCP usado por el servidor LDAP"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Usa una conexión segura"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Usa una conexión SSL/TLS para acceder al servidor LDAP"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Método de autenticación"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Buscar y unir"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Unión directa"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Elegir el método de autenticación a usar"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Unir a DN"
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -115,24 +146,30 @@ msgid ""
msgstr ""
"El nombre distinguido a usar cuando nos unimos al servidor LDAP. Dejar vació "
"para una unión anónima"
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Unir contraseña"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"La contraseña a usar cuando nos unimos al servidor LDAP (con 'Unir a DN')"
+
#: core/app_settings.py:134
#, fuzzy
msgid "Users search base"
msgstr "Buscar base"
+
#: core/app_settings.py:137
#, fuzzy
msgid "The distinguished name of the search base used to find users"
msgstr "El nombre disgituido de la búsqueda base"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtro de búsqueda"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -140,9 +177,11 @@ msgid ""
msgstr ""
"Una cadena de filtro opcional (p.e. '(objectClass=person)'). Para que sea "
"válido tiene que ser encerrado entre paréntesis."
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Plantilla DN del usuario"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -151,296 +190,381 @@ msgid ""
msgstr ""
"La plantilla usada para contriunr un DN de usuario. Debería contener una "
"cadena reemplazables (p.e. %(user)s)"
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Atributo de la contraseña"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "El atributo usado para guardar las contraseñas del usuario"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Directorio Activo"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Decir si el servidor de LDAP es uno del tipo Directorio Activo"
+
#: core/app_settings.py:180
#, fuzzy
msgid "Administrator groups"
msgstr "Administradores"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
msgstr ""
+
#: core/app_settings.py:190
#, fuzzy
msgid "Groups search base"
msgstr "Buscar base"
+
#: core/app_settings.py:193
#, fuzzy
msgid "The distinguished name of the search base used to find groups"
msgstr "El nombre disgituido de la búsqueda base"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Otros"
+
#: core/app_settings.py:201
#, fuzzy
msgid "Top notifications check interval"
msgstr "Notificaciones al remitente"
+
#: core/app_settings.py:203
#, fuzzy
msgid "Interval between two top notification checks"
msgstr "Intervalo entre dos peticiones de chequeo"
+
#: core/app_settings.py:208
#, fuzzy
msgid "Check new versions"
msgstr "Marcar para activar esta extensión"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr ""
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Máximo tiempo de almacenamiento del log"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "El tiempo máximo de almacenamiento del log en días"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Items por página"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Número de elementos mostrado por página"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Redirección principal por defecto"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"La redirección que será usada cuando ninguna aplicación sea especificada."
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "La clave debe tener 16, 24 o 32 bytes de longitud"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Sintaxis inválida"
+
#: core/app_settings.py:278
#, fuzzy
msgid "Invalid rounds number"
msgstr "Petición inválida"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Este campo es obligatorio"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Mostrar"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Idioma preferido"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Idioma preferido para mostrar las páginas"
+
#: core/forms.py:14
msgid "Username"
msgstr "Nombre de usuario"
+
#: core/forms.py:18
msgid "Password"
msgstr "Contraseña"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Contraseña anterior"
+
#: core/forms.py:33
msgid "New password"
msgstr "Nueva contraseña"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Confirmación"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "La contraseña no concuerda con la anterior"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Las contraseñas no coinciden"
+
#: core/models.py:52
#, fuzzy
msgid "password"
msgstr "Contraseña"
+
#: core/models.py:54
#, fuzzy
msgid "last login"
msgstr "Última entrada"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "No puede eliminar su propia cuenta"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Falló al actualizar la contraseña: módulo LDAP no instalado"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "cuenta"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Línea inválida"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "No puede importar una cuenta con un rol mayor que el suyo"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "El usuario normal '%s' debe tener una dirección de email válida"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr ""
"Los campos de nombre de usuario y de email no deben ser diferentes para '%s'"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "añadido"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "modificado"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s por el usuario %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "eliminado"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Extensiones"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Elija las extensión(es) a usar"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Nombre"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Versión"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Descripción"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Información"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Información varia sobre Modoboa"
+
#: core/templates/core/information.html:5
#, fuzzy
-msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "No hay estadísticas disponibles"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "está actualmente en uso."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Autenticación"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Nombre"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Última entrada"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Descripción"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Usuarios activos"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Nombre del grupo"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Última entrada"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Logs"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Anteriormente en Modoboa..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Fecha"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Nivel"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Mensaje"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Parámetros"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configurar Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Guardar"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Configuración de Modoboa"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Configuración"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Preferencias"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Adaptar Modoboa"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Perfil"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Actualizar su información personal"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Actualizar"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Salir"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Bienvenido a Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Parámetros guardados"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Usuario '%s' ha entrado con éxito"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Su nombre de usuario y contraseña no concuerdan. Por favor, inténtelo de "
"nuevo."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Usuario '%s' ha salido"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Perfil actualizado"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Preferencias guardadas"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Mensajes de test"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Enviar virus"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Enviar correo basura"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -472,182 +596,135 @@ msgstr ""
"a \n"
" la lista "
"de correo .\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Mensaje enviado"
+
#: lib/db_utils.py:39
#, fuzzy, python-format
msgid "Connection to database %s not configured"
msgstr "La conexión con amavis falló: %s"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Permiso denegado: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Permiso denegado"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr ""
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Petición inválida"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Introduzca un nombre dominio válido"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Sí"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "No "
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Falló la actualización de la contraseña: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Usuario normal"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super administrador"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Administrador de dominio"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Lo siento"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "La página pedida no existe."
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Ocurrió un error interno."
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Buscar..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "De la dirección"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Tema"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Ambos"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Error:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Ayuda:"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Cerrar"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Anterior"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Siguiente"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Bienvenido a Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Recuerdame"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Entrar"
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
+
+#~ msgid "Extensions"
+#~ msgstr "Extensiones"
+
+#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Elija las extensión(es) a usar"
+
+#~ msgid "Version"
+#~ msgstr "Versión"
+
+#~ msgid "is currently in use."
+#~ msgstr "está actualmente en uso."
diff --git a/modoboa/locale/es/LC_MESSAGES/djangojs.po b/modoboa/locale/es/LC_MESSAGES/djangojs.po
index 975e07ec2..5c76e256f 100644
--- a/modoboa/locale/es/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/es/LC_MESSAGES/djangojs.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2013-06-03 16:32+0000\n"
"Last-Translator: Pedro Gracia \n"
"Language-Team: Spanish (http://www.transifex.com/projects/p/modoboa/language/"
@@ -19,27 +19,32 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr ""
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Aviso"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Cancelar"
+
#: static/js/global.js:329
#, fuzzy
msgid "Internal error"
msgstr "Error interno"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr ""
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Buscar"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Buscar..."
-#, fuzzy
-#, fuzzy
diff --git a/modoboa/locale/fr/LC_MESSAGES/django.po b/modoboa/locale/fr/LC_MESSAGES/django.po
index a204f0484..feb9a1f45 100644
--- a/modoboa/locale/fr/LC_MESSAGES/django.po
+++ b/modoboa/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: modoboa-1.1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2011-01-07 10:00+100\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: FR \n"
@@ -16,49 +16,66 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Général"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr "Nouvelle version de Modoboa disponible"
+
+#: core/__init__.py:85
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available"
+msgstr "Une mise à jour est disponible!"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Authentification"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Type d'authentification"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Locale"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Le backend utilisé pour l'authentification"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Méthode de chiffrement par défaut"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (faible)"
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (faible)"
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (faible)"
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (faible)"
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (faible)"
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr ""
"Méthode utilisée pour chiffrer les mots de passe des boites aux lettres"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr "Tours"
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
@@ -66,48 +83,63 @@ msgid ""
msgstr ""
"Nombre de tours à utiliser (sha256crypt et sha512crypt uniquement). Doit "
"être compris entre 1000 et 999999999 inclue."
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Clé secrète"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Clé utilisée pour chiffrer/déchiffre les mots de passe"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Paramètres LDAP"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Adresse du serveur"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "L'adresse IP ou le nom DNS du serveur LDAP"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Port utilisé par le serveur"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Le port TCP utilisé par le serveur LDAP"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Utiliser une connexion sécurisée"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Utiliser une connextion SSL/TLS pour accéder au serveur LDAP"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Méthode d'authentification"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Recherche et connexion"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Connexion directe"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Choisir la méthode d'authentification à utiliser"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "ND de connexion"
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -115,25 +147,31 @@ msgid ""
msgstr ""
"Le nom distinctif à utiliser pour les connections au serveur LDAP. Laisser "
"vide pour une connexion anonyme"
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Mot de passe de connexion"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"Le mot de passe à utiliser pour les connections au serveur LDAP (avec 'ND de "
"connexion')"
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr "Base de recherche des utilisateurs"
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr ""
"Le nom distinctif de la base de recherche utilisée pour rechercher les "
"utilisateurs"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtre de recherche"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -141,9 +179,11 @@ msgid ""
msgstr ""
"Un filtre de recherche optionel (ex. '(objectClass=person)'). Pour être "
"valide, il doit être entouré de parenthèses."
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Modèle de nom distinctif utilisateur"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -152,21 +192,27 @@ msgid ""
msgstr ""
"Le modèle utilisé pour construire le nom distinctif d'un utilisateur. Il "
"doit contenir un espace réservé (ex. %(user)s)"
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Attribut 'mot de passe'"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "L'attribut utilisé pour stocker les mots de passe"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Indiquer si le serveur LDAP est un Active Directory ou pas"
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Groupes administrateurs"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
@@ -175,273 +221,349 @@ msgstr ""
"Les membres de ces groupes LDAP (Posix) seront créés en tant "
"qu'administrateurs de domaine. Utiliser des caractères ';' pour séparer les "
"groupes."
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Base de recherche des groupes"
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr ""
"Le nom distinctif de la base de recherche utilisée pour rechercher les "
"groupes"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Divers"
+
#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Intervalle de vérification des notifications"
+
#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Intervalle entre deux vérifications de notification"
+
#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Vérifier les nouvelles versions"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Vérifie automatiquement si une nouvelle version est disponible"
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Age maximal d'un enregistrement du journal"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "L'age maximal en jours d'un enregistrement du journal"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Eléments par page"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Nombre d'éléments affichés par page"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Redirection par défaut"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"La redirection appliquée par défaut quand aucune application n'est spécifiée"
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "La longueur d'une clé doit être de 16, 24 ou 32 octets"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Syntaxe invalide"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Nombre invalide de tours"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Ce champ est requis"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Afficher"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Langage préféré"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Langage préféré pour afficher les pages"
+
#: core/forms.py:14
msgid "Username"
msgstr "Nom d'utilisateur"
+
#: core/forms.py:18
msgid "Password"
msgstr "Mot de passe"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Ancien mot de passe"
+
#: core/forms.py:33
msgid "New password"
msgstr "Nouveau mot de passe"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Confirmation"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "L'ancien mot de passe est incorrect"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Les mots de passe diffèrent"
+
#: core/models.py:52
msgid "password"
msgstr "mot de passe"
+
#: core/models.py:54
msgid "last login"
msgstr "dernière connexion"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Vous ne pouvez pas supprimer votre propre compte"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr ""
"Echec de la mise à jour du mot de passe : le module LDAP n'est pas installé"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "compte"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Ligne invalide"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "Vous ne pouvez pas importer un compte avec un rôle supérieur au votre"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "L'utilisateur simple '%s' doit avoir une adresse email valide"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "Les champs username et email de '%s' ne doivent pas différer"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "ajouté"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "modifié"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s par l'utilisateur %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "Supprimé"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Extensions"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Choisir les extensions à utiliser"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Nom"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Version"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Description"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Information"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informations variées à propos de Modoboa"
+
#: core/templates/core/information.html:5
-msgid "An update is available!"
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "Une mise à jour est disponible!"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-"\n"
-" Modoboa %(version)s est disponible au téléchargement. La "
-"liste des changements est disponible ici .\n"
-" "
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "est actuellement utilisé."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Authentification"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Nom"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Dernière connexion"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Description"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Utilisateurs actifs"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Nom du groupe"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Dernière connexion"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Journaux"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Précédemment dans Modoboa..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Date"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Niveau"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Message"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Paramètres"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configurez Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Enregistrer"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Paramètres de Modoboa"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Configuration"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Préférences"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Personnalisez Modoboa"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Profil"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Mettez à jour vos informations personnelles"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Mettre à jour"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Déconnexion"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Bienvenue dans Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Paramètres enregistrés"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Utiliseur '%s' connecté avec succès"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Votre nom d'utilisateur et mot de passe ne correspondent pas. Veuillez "
"réessayer."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Utilisateur '%s' déconnecté"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profil mis à jour"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Préférences enregistrées"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Message de test"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Envoyer un virus"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Envoyer un spam"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -472,93 +594,151 @@ msgstr ""
"Veuillez svp rapporter toute erreur sur \n"
" la liste "
"de diffusion .
\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Message envoyé"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Connexion à la base de données %s non configurée"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Permission refusée : %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Permission refusée"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr "Soumettre"
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Requête invalide"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Entrer un nom de domaine valide"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Oui"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "Non"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Echec de la mise à jour du mot de passe : %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Utilisateur simple"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super administrateur"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Administrateur de domaine"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Désolé"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "La page demandée n'existe pas."
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Une erreur interne est survenue"
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Chercher..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Emetteur"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Sujet"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Tous"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Erreur :"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Aide :"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Fermer"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Précédent"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Suivant"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Bienvenue dans Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Se souvenir de moi"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Se connecter"
+
+#~ msgid "New Modoboa version available"
+#~ msgstr "Nouvelle version de Modoboa disponible"
+
+#~ msgid "Extensions"
+#~ msgstr "Extensions"
+
+#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Choisir les extensions à utiliser"
+
+#~ msgid "Version"
+#~ msgstr "Version"
+
+#~ msgid ""
+#~ "\n"
+#~ " Modoboa %(version)s is available for download. The "
+#~ "list of all changes is available here .\n"
+#~ " "
+#~ msgstr ""
+#~ "\n"
+#~ " Modoboa %(version)s est disponible au téléchargement. "
+#~ "La liste des changements est disponible ici .\n"
+#~ " "
+
+#~ msgid "is currently in use."
+#~ msgstr "est actuellement utilisé."
diff --git a/modoboa/locale/fr/LC_MESSAGES/djangojs.po b/modoboa/locale/fr/LC_MESSAGES/djangojs.po
index e5e6bbbd3..b6fd3b811 100644
--- a/modoboa/locale/fr/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/fr/LC_MESSAGES/djangojs.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: modoboa-1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2011-01-07 10:00+0100\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: FR \n"
@@ -16,24 +16,31 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Plus d'entrée de journal à afficher"
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Avertissement"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Annuler"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr "Erreur interne"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Plus d'entrée à afficher"
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Chercher"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Chercher..."
diff --git a/modoboa/locale/it/LC_MESSAGES/django.po b/modoboa/locale/it/LC_MESSAGES/django.po
index ee7218d0e..fcc0b5fd8 100644
--- a/modoboa/locale/it/LC_MESSAGES/django.po
+++ b/modoboa/locale/it/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2013-12-23 00:56+0100\n"
"Last-Translator: Alberto Berti \n"
"Language-Team: ITALIANO \n"
@@ -16,49 +16,65 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Generale"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr ""
+
+#: core/__init__.py:85
+#, fuzzy
+msgid "One or more updates are available"
+msgstr "Non sono disponibili statistiche"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autenticazione"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Tipo di autenticazione"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Locale"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Il backend utilizzato per l'autenticazione"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Schema password predefinito"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (debole)"
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (debole)"
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (debole)"
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (debole)"
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (debole)"
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr ""
"Schema utilizzato per la criptazione delle password delle caselle di posta"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr "Cicli"
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
@@ -66,48 +82,63 @@ msgid ""
msgstr ""
"Numero di cicli da utilizzare (valido per sha256crypt e sha512crypt). "
"Dev'essere tra 1000 e 999999999, inclusivo."
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Chiave segreta"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Chiave utilizzata per criptare/decriptare le password"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Impostazioni LDAP"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Indirizzo del server"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "L'indirizzo IP associato al DNS name del server LDAP"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Porta del server"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Il numero della porta TCP utilizzata dal server LDAP"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Usa una connessione sicura"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Utilizza una connessione SSL/TLS per accedere al server LDAP"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Metodo di autenticazione"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Cerca e collega"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Collegamento diretto"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Scegli il metodo di autenticazione da usare"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "collega DN"
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -115,25 +146,31 @@ msgid ""
msgstr ""
"Nome particolare da usare quando ci si collega al server LDAP. Lasciare "
"vuoto per un collegamento anonimo"
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Password del collegamento"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"La password da utilizzare quando ci si collega al server LDAP (con 'Collega "
"DN')"
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr "Base ricerca per gli utenti"
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr ""
"L'identificativo (dn:) della base di ricerca utilizzata per cercare gli "
"utenti"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtro ricerca"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -141,9 +178,11 @@ msgid ""
msgstr ""
"Stringa di filtraggio opzionale (p.es '(objectClass=person)'). Per essere "
"valida deve essere racchiusa tra parentesi."
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Modello DN dell'utente"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -152,21 +191,27 @@ msgid ""
msgstr ""
"Il modello utilizzato per comporre un DN dell'utente. Deve contenere un "
"segnaposto (p.es. %(user)s)"
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Attributo della password"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "L'attributo utilizzato per memorizzare le password dell'utente"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Segnala se il server LDAP è una Active Directory"
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Gruppi degli amministratori"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
@@ -175,269 +220,348 @@ msgstr ""
"Gli appartenenti a questi gruppi LDAP Posix avranno i privilegi di "
"amministratori di dominio. Utilizza il carattere ';' per separare valori "
"multipli."
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Base ricerca per i gruppi"
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr ""
"L'identificatore (dn:) della base di ricerca utilizzato per trovare i gruppi"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Miscellanea"
+
#: core/app_settings.py:201
#, fuzzy
msgid "Top notifications check interval"
msgstr "Spedizione notifiche"
+
#: core/app_settings.py:203
#, fuzzy
msgid "Interval between two top notification checks"
msgstr "Intervallo tra due controlli delle request di rilascio "
+
#: core/app_settings.py:208
#, fuzzy
msgid "Check new versions"
msgstr "Verifica validità destinatari"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr ""
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Età massima dei log"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "La persistenza massima in giorni dei log"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Elementi per pagina"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Numero degli elementi visualizzati in ciascuna pagina"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Reindirizzamento principale predefinito"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"Redirezione predefinita utilizzata quando non è specificata alcuna "
"applicazione"
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "La chiave può essere lunga solo 16, 24 o 32 bytes"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Sintassi errata"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Numero di cicli non valido"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Questo campo è obbligatorio"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Mostra"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Lingua preferita"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Lingua preferita per mostrare le pagine"
+
#: core/forms.py:14
msgid "Username"
msgstr "Nome utente"
+
#: core/forms.py:18
msgid "Password"
msgstr "Password"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Vecchia password"
+
#: core/forms.py:33
msgid "New password"
msgstr "Nuova password"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Conferma"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "La vecchia password non corrisponde"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "La password non corrisponde"
+
#: core/models.py:52
msgid "password"
msgstr "password"
+
#: core/models.py:54
msgid "last login"
msgstr "ultimo login"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Non puoi cancellare il tuo account"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Aggiornamento della password fallito: il modulo LDAP non è installato"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "account"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Riga non valida"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "Non puoi importare un account con un ruolo superiore al tuo"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "L'utente '%s' deve avere un indirizzo email valido"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "I campi nome utente e email di '%s' devono avere lo stesso valore"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "aggiunto"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "modificato"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s dell'utente %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "cancellato"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Estensioni"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Scegli l'estensione(i) da utilizzare"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Nome"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Versione"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Descrizione"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Informazioni"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informazioni varie su Modoboa"
+
#: core/templates/core/information.html:5
#, fuzzy
-msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "Non sono disponibili statistiche"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "è attualmente in uso."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Autenticazione"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Nome"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Ultimo login"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Descrizione"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Utenti attivi"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Nome gruppo"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Ultimo login"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Log"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Precedentemente su Modoboa ..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Data"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Livello"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Messaggio"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Parametri"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configura Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Salva"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Impostazioni Modoboa"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Impostazioni"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Preferenze"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Personalizza Modoboa"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Profilo"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Aggiorna le informazioni personali"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Aggiorna"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Esci"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Benvenuti in Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Parametri salvati"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "L'utente '%s? è correttamente registrato"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "Il tuo username e/o la tua password non corrispondono. Riprova."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "L'utente '%s' è scollegato"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profilo aggiornato"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Preferenze salvate"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Messaggi di test"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Invia virus"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Invia spam"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -469,133 +593,135 @@ msgstr ""
"Prego segnalare qualsiasi errore o inviare suggerimenti \n"
" alla \n"
"mailing list .
\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Messaggio inviato"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "La connessione con il database %s non è configurata"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Accesso negato: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Accesso negato"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr ""
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Richiesta non valida"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Inserisci un nome di dominio valido"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Si"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "No"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Aggiornamento della password fallito: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Utente semplice"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super amministratore"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Amministratore di domini"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Dispiace"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "La pagina richiesta non esiste"
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "È intervenuto un errore interno"
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Ricerca ..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Mittente"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Oggetto"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Entrambi"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Errore:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Aiuto"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Chiudi"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Precedente"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Successivo"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Benvenuti in Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Ricordami"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Registrati"
+
+#~ msgid "Extensions"
+#~ msgstr "Estensioni"
+
#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Scegli l'estensione(i) da utilizzare"
+
+#~ msgid "Version"
+#~ msgstr "Versione"
+
+#~ msgid "is currently in use."
+#~ msgstr "è attualmente in uso."
diff --git a/modoboa/locale/it/LC_MESSAGES/djangojs.po b/modoboa/locale/it/LC_MESSAGES/djangojs.po
index 25a134486..f1150a9db 100644
--- a/modoboa/locale/it/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/it/LC_MESSAGES/djangojs.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2013-12-23 00:58+0100\n"
"Last-Translator: Alberto Berti \n"
"Language-Team: Italiano \n"
@@ -16,26 +16,31 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr ""
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Attenzione"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Elimina"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr "Errore interno"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr ""
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Ricerca"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Ricerca ..."
-#, fuzzy
-#, fuzzy
diff --git a/modoboa/locale/nl_NL/LC_MESSAGES/django.po b/modoboa/locale/nl_NL/LC_MESSAGES/django.po
index eac909247..bff69a9c8 100644
--- a/modoboa/locale/nl_NL/LC_MESSAGES/django.po
+++ b/modoboa/locale/nl_NL/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2014-12-31 11:37+0000\n"
"Last-Translator: TuxBrother \n"
"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/"
@@ -19,48 +19,65 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Algemeen"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr "Er is een nieuwe versie van Modoboa beschikbaar!"
+
+#: core/__init__.py:85
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available"
+msgstr "Er is een update beschikbaar!"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Authenticatie"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Authenticatie type"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Lokaal"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "De backend gebruikt voor authenticatie"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Standaard wachtwoord encryptiemethode"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (zwak)"
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (zwak)"
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (zwak)"
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (zwak)"
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (onversleuteld!)"
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Schema dat gebruikt word om mailbox wachtwoorden te versleutelen"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr "Rondes"
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
@@ -68,48 +85,63 @@ msgid ""
msgstr ""
"Nummer van te gebruiken randomizeringsrondes (alleen bij sha256crypt en "
"sha512crypt). Moet tussen de 1000 en 999999999 liggen."
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Geheime sleutel"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Code die gebruikt word om wachtwoorden te versleutelen/ontsleutelen"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "LDAP instellingen"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Server adres"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "Het IP adres en de DNS naam van LDAP server"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Server poort"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Het TCP poortnummer gebruikt door de LDAP server"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Gebruik een beveiligde verbinding"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Gebruik een SSL/TLS verbinding met de LDAP server"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Authenticatie methode"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Zoeken en koppelen"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Directe koppeling"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Kies een authenticatie methode om te gebruiken"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Koppeling DN"
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -117,23 +149,29 @@ msgid ""
msgstr ""
"De gedistingeerde naam om te gebruiken bij het koppeling met de LDAP server. "
"Laat leeg voor een anonieme koppeling."
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Koppel wachtwoord"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"Het wachtwoord om te gebruiken tijdens het koppelen met de LDAP server (met "
"'koppel DN')"
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr "Gebruikers zoekbasis"
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "De gedistingeerde naam van de zoekbasis om gebruikers te vinden"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Zoek filter"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -141,9 +179,11 @@ msgid ""
msgstr ""
"Een optionele filter string (zoals '(objectClass=person)'). Om geldig te "
"kunnen zijn, moet het ingesloten zijn tussen haakjes."
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Gebruiker DN template"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -152,21 +192,27 @@ msgid ""
msgstr ""
"Het template dat gebruikt word om een gebruiker zijn/haar DN op te bouwen. "
"Het moet een placeholder bevatten (bijvoorbeeld. %(user)s)"
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Wachtwoord attribuut"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Dit attribuut word gebruikt om wachtwoorden op te slaan"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "De LDAP server is een Active Directory"
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Administrator groepen"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
@@ -174,270 +220,347 @@ msgid ""
msgstr ""
"Leden van deze LDAP POSIX groepen zullen aangemaakt worden als domein "
"administrators. Gebruik ';' karakters om groepen te scheiden."
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Groepen zoek basis"
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "De gedistingeerde naam van de zoekbasis om groepen te vinden"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Diversen"
+
#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Top notificaties controle interval"
+
#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Interval tussen twee top notificatie checks"
+
#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Controleer of er een nieuwe versie beschikbaar is"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Automatische controle voor nieuwe versies"
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Maximum bewaartijd van logs"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "De maximum bewaartijd in dagen van een log record"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Items per pagina"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Hoeveelheid items per pagina"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Standaard top omleiding"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"De standaard omleiding die gebruikt word als er geen andere applicatie is "
"opgegeven"
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Sleutelwaarde moet 16, 24 of 32 bytes lang zijn"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Ongeldige zinsbouw"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Ongeldig nummer van rondes"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Dit veld is benodigd"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Weergeven"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Voorkeurs taal"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Voorkeurstaal om pagina's weer te geven"
+
#: core/forms.py:14
msgid "Username"
msgstr "Gebruikersnaam"
+
#: core/forms.py:18
msgid "Password"
msgstr "Wachtwoord"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Oud wachtwoord"
+
#: core/forms.py:33
msgid "New password"
msgstr "Nieuw wachtwoord"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Bevestiging"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Oud wachtwoord komt niet overeen"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Wachtwoorden komt niet overeen"
+
#: core/models.py:52
msgid "password"
msgstr "wachtwoord"
+
#: core/models.py:54
msgid "last login"
msgstr "laatste login"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "U kunt uw eigen account niet verwijderen"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Mislukt om wachtwoord aan te passen: LDAP module niet geinstalleerd"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "account"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Verkeerde regel"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "U kunt geen accounts importeren met hogere rechten dan die van uzelf."
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "De gebruiker '%s' moet een geldig email adres hebben"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "gebruikersnaam en email velden moeten niet verschillen van '%s'"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "toegevoegd"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "veranderd"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s door gebruiker %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "verwijderd"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Extensies"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Kies de extensie(s) om te gebruiken"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Naam"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Versie"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Beschrijving"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Informatie"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informatie over Modoboa"
+
#: core/templates/core/information.html:5
-msgid "An update is available!"
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "Er is een update beschikbaar!"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-"\n"
-"Modoboa %(version)s is beschikbaar om te downloaden. De "
-"lijst met alle veranderingen is hier beschikbaar."
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "is momenteel in gebruik."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Authenticatie"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Naam"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Laatste login"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Beschrijving"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Actieve gebruikers"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Groep naam"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Laatste login"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Logs"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Vorige gebeurtenissen op Modoboa..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Datum"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Niveau"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Bericht"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Parameters"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configureer Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Opslaan"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Instellingen van Modoboa"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Instellingen"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Voorkeuren"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Modoboa aanpassen"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Profiel"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Persoonlijke informatie aanpassen"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Toepassen"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Uitloggen"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Welkom bij Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Parameters opgeslagen"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Gebruiker '%s' successvol aangemeld"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Uw gebruikersnaam en wachtwoord komen niet overeen. Probeer het alstublief "
"opnieuw."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Gebruiker '%s' heeft afgemeld"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profiel aangepast"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Voorkeuren opgeslagen"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Testberichten"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Verstuur virus"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Verstuur spam"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -469,93 +592,150 @@ msgstr ""
"maillijst .\n"
"Fouten gevonden in de Nederlandse vertaling? Geef uw opmerkingen of "
"suggesties door aan: foss at waut punt nl
\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Bericht verstuurd"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Verbinding naar database %s niet ingesteld"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Toegang geweigerd: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Toegang geweigerd"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr "Versturen"
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Ongeldig verzoek"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Vul een geledige domeinnaam in"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Ja"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "Nee"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Mislukt om wachtwoord aan te passen: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Gebruiker"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Hoofdbeheerder"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Domein administrator"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Sorry"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "De opgegeven pagina bestaat niet."
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Er is een interne fout opgetreden."
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Zoeken..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Van adres"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Onderwerp"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Beiden"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Foutmelding:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Help:"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Sluiten"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Vorige"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Volgende"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Welkom bij Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Onthoud mij"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Inloggen"
+
+#~ msgid "New Modoboa version available"
+#~ msgstr "Er is een nieuwe versie van Modoboa beschikbaar!"
+
+#~ msgid "Extensions"
+#~ msgstr "Extensies"
+
+#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Kies de extensie(s) om te gebruiken"
+
+#~ msgid "Version"
+#~ msgstr "Versie"
+
+#~ msgid ""
+#~ "\n"
+#~ " Modoboa %(version)s is available for download. The "
+#~ "list of all changes is available here .\n"
+#~ " "
+#~ msgstr ""
+#~ "\n"
+#~ "Modoboa %(version)s is beschikbaar om te downloaden. De "
+#~ "lijst met alle veranderingen is hier beschikbaar."
+
+#~ msgid "is currently in use."
+#~ msgstr "is momenteel in gebruik."
diff --git a/modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po b/modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po
index d0300f3e7..f990a6b2c 100644
--- a/modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/nl_NL/LC_MESSAGES/djangojs.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2014-12-31 11:42+0000\n"
"Last-Translator: TuxBrother \n"
"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/"
@@ -19,24 +19,31 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Geen log bericht meer om te weergeven"
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Waarschuwing"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Annuleren"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr "Interne fout"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Geen bericht meer om te weergeven"
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Zoeken"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Zoeken..."
diff --git a/modoboa/locale/pt_BR/LC_MESSAGES/django.po b/modoboa/locale/pt_BR/LC_MESSAGES/django.po
index 92009e34f..1044e6e32 100644
--- a/modoboa/locale/pt_BR/LC_MESSAGES/django.po
+++ b/modoboa/locale/pt_BR/LC_MESSAGES/django.po
@@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2014-12-13 09:10+0000\n"
"Last-Translator: Paulino Michelazzo \n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
@@ -20,48 +20,65 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Geral"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr "Nova versão do Modoboa disponível"
+
+#: core/__init__.py:85
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available"
+msgstr "Uma atualização está disponível!"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autenticação"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Tipo de autenticação"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Local"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "O backend usado para autenticação"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Esquema padrão de senha"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (fraca)"
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (fraca)"
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (fraca)"
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (fraca)"
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (fraca)"
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Esquema usado para criptografar as senhas das caixas de correio"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr "Voltas"
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
@@ -69,48 +86,63 @@ msgid ""
msgstr ""
"Número de voltas a serem usadas (somnete usadas por sha256crypt e "
"sha512crypt). Deve estar entre 1000 e 999999999, inclusive."
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Chave secreta"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Chave utilizada para encriptar/decriptar senhas"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Configurações do LDAP"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Endereço do servidor"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "O endereço IP do nome DNS do servidor LDAP"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Porta do servidor"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "O número da porta TCP usada pelo servidor LDAP"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Usar conexão segura"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Usar uma conexão SSL/TLS para acessar o servidor LDAP"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Método de autenticação"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Pesquisar e vincular"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Vinculação direta"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Escolha o método de autenticação para usar"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Vincular DN"
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -118,21 +150,27 @@ msgid ""
msgstr ""
"O nome distinguível para usar quando vincular ao servidor LDAP. Deixe vazio "
"para vincular anonimamente"
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Vincular senha"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr "A senha usada quando vincular ao servidor LDAP (com 'Vincular DN')"
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr "Base de pesquisa de usuários"
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "O nome distinto da base de pesquisa usada para encontrar usuários"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtro de pesquisa"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -140,9 +178,11 @@ msgid ""
msgstr ""
"Uma string opcional de filtro (por ex: '(objectClass=person)'). Para ser "
"válida, deve estar entre parênteses."
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Usar template DN"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -151,21 +191,27 @@ msgid ""
msgstr ""
"A template usada para construir um DN de usuário. Deve conter um placeholder "
"(por ex: %(user)s)"
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Atributo de senha"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "O atributo usado para armazenar senhas de usuários"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Informe se o servidor LDAP é um Active Directory"
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Grupos de administradores"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
@@ -173,268 +219,344 @@ msgid ""
msgstr ""
"Membros dos grupos do LDAP Posix serão criados como administradores de "
"domínio. Use o caractere ';' para separar grupos."
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Base de pesquisa de grupos"
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "O nome distinto da base de pesquisa usada para encontrar grupos"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Miscelânea"
+
#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Intervalo de verificação de verificações de topo"
+
#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Intervalo entre duas notificações de verificações de topo"
+
#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Verificar novas versões"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Verificar automaticamente se uma nova versão está disponível"
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Idade máxima do registro de log"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "A idade máxima em dias de um registro de log"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Itens por página"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Número de itens exibidos por página"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Redirecionamento de topo padrão"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"O redirecionamento padrão usado quando nenhuma aplicação é especificada"
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "A chave deve ter 16, 24 ou 32 bytes de tamanho"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Sintaxe inválida"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Número de voltas inválido"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Este campo é obrigatório"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Mostrar"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Idioma preferido"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Idioma preferido para exibir páginas"
+
#: core/forms.py:14
msgid "Username"
msgstr "Nome de usuário"
+
#: core/forms.py:18
msgid "Password"
msgstr "Senha"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Senha antiga"
+
#: core/forms.py:33
msgid "New password"
msgstr "Nova senha"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Confirmação"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Senha antiga não confere"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Senhas não conferem"
+
#: core/models.py:52
msgid "password"
msgstr "senha"
+
#: core/models.py:54
msgid "last login"
msgstr "último login"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Você não pode deletar sua própria conta"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Falha ao atualizar senha: módulo LDAP não instalado"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "conta"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Linha inválida"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "Você não pode importar uma conta com um papel maior que o seu"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "O usuário simples '%s' deve ter um endereço de e-mail válido"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "os campos nome de usuário e e-mail não diferem de '%s'"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "adicionado"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "modificado"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s pelo(s) usuário(s) %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "apagado"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Extensões"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Escolha a(s) extensão(ões) para usar"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Nome"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Versão"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Descrição"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Informação"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informações diversas sobre Modoboa"
+
#: core/templates/core/information.html:5
-msgid "An update is available!"
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "Uma atualização está disponível!"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-"\n"
-" O Modoboa %(version)s está disponível para download. A "
-"lista de todas as alterações está disponível aqui .\n"
-" "
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "atualmente em uso."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Autenticação"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Nome"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Último login"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Descrição"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Usuários ativos"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Nome do grupo"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Último login"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Logs"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Previamente no Modoboa..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Data"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Nível"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Mensagem"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Parâmetros"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configurar o Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Salvar"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Configurações do Modoboa"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Configurações"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Preferências"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Customizar Modoboa"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Perfil"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Atualizar sua informação pessoal"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Atualizar"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Sair"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Bem-vindo ao Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Parêmetros salvos"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Usuário '%s' autenticado com successo"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "Seu usuário e senha não conferem. Por favor tente novamente."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "O usuário '%s' saiu"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Perfil atualizado"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Preferências salvas"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Testar mensagens"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Enviar vírus"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Envia spam"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -465,93 +587,151 @@ msgstr ""
"Por favor, reporte qualquer problema ou faça alguma sugestão \n"
"na lista "
"de discussão .
\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Mensagem enviada"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "A conexão com o banco de dados %s não está configurada"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Permissão negada: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Permissão negada"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr "Enviar"
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Solicitação inválida"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Digite um nome de domínio válido"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Sim"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "Não"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Falha ao atualizar senha: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Usuário simples"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super administrador"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Administrador de domínio"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Desculpe"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "A página solicitada não existe."
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Um erro interno ocorreu."
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Buscar..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Do endereço"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Assunto"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Ambos"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Erro:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Ajuda:"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Fechar"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Anterior"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Próximo"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Bem-vindo ao Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Lembrar-me"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Entrar"
+
+#~ msgid "New Modoboa version available"
+#~ msgstr "Nova versão do Modoboa disponível"
+
+#~ msgid "Extensions"
+#~ msgstr "Extensões"
+
+#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Escolha a(s) extensão(ões) para usar"
+
+#~ msgid "Version"
+#~ msgstr "Versão"
+
+#~ msgid ""
+#~ "\n"
+#~ " Modoboa %(version)s is available for download. The "
+#~ "list of all changes is available here .\n"
+#~ " "
+#~ msgstr ""
+#~ "\n"
+#~ " O Modoboa %(version)s está disponível para download. A "
+#~ "lista de todas as alterações está disponível aqui .\n"
+#~ " "
+
+#~ msgid "is currently in use."
+#~ msgstr "atualmente em uso."
diff --git a/modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po b/modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po
index 9b7ed77c4..34de7123f 100644
--- a/modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/pt_BR/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2014-12-13 09:14+0000\n"
"Last-Translator: Paulino Michelazzo \n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
@@ -18,24 +18,31 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Nenhuma entrada de log a mais para mostrar"
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Atenção"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Cancelar"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr "Erro interno"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Nenhuma entrada a mais para mostrar"
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Busca"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Buscar..."
diff --git a/modoboa/locale/pt_PT/LC_MESSAGES/django.po b/modoboa/locale/pt_PT/LC_MESSAGES/django.po
index 9a5962132..2b7c1372c 100644
--- a/modoboa/locale/pt_PT/LC_MESSAGES/django.po
+++ b/modoboa/locale/pt_PT/LC_MESSAGES/django.po
@@ -13,7 +13,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2014-12-29 12:51+0000\n"
"Last-Translator: Mike C. \n"
"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/"
@@ -23,95 +23,127 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Geral"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr "Existem uma nova versão do Modoboa disponivel"
+
+#: core/__init__.py:85
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available"
+msgstr "Uma nova versão está disponível!"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autenticação"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Tipo de autenticação"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Local"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Backend usado para autenticação"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Esquema pré-definido para passwords"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (fraco)"
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (fraco)"
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (fraco)"
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (fraco)"
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "plain (fraco)"
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Esquema usado para encriptar as passwords das caixas de correio"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr ""
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Chave secreta"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Chave usada para encriptar/desencriptar passwords"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Definições do serviço de directório"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Endereço do Servidor"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "O endereço IP do servidor de DNS do servidor LDAP"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Porta do Servidor"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr " A porta TCP usada pelo servidor LDAP"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Utilizar uma ligação segura"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Usar SSL/TLS na ligaçao de acesso ao servidor LDAP"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Método de autenticação"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Procurar e vincular (bind)"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "\"Direct bind\""
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Escolher o método de autenticação"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "\"Bind DN\""
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -119,22 +151,28 @@ msgid ""
msgstr ""
"O nome único usado para fazer o \"bind\" ao servidor LDAP. Deixar vario "
"para \"bind\" anónimo"
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Password para bind"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"A password usada para fazer o \"bind\" ao servidor LDAP (com 'Bind DN')"
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr "Base para pesquisa de utilizadores"
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "O nome único a usar para pesquisa de utilizadores"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Filtro de pesquisa"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -142,9 +180,11 @@ msgid ""
msgstr ""
"Um filtro opcional (ex: '(objetClass=person)'). Tem de estar entre "
"parênteses para ser válido"
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Template DN de utilizador"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -153,21 +193,27 @@ msgid ""
msgstr ""
"O template usado para construir o DN (nome único). Deve apenas conter um "
"'placeholder' (ex: %(user)s) "
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Atributo de palavra-passe"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "O atributo utilizado para armazenar palavras-passe"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Especificar se o servidor LDAP e um Active Directory"
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Grupos de Administrador"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
@@ -175,266 +221,347 @@ msgid ""
msgstr ""
"Os membros destes grupos \"LDAP Posix\" serão criados como administradores "
"de domínio. Use ';' para separar os grupos."
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Base para pesquisa de Grupos"
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "O nome único para a base de pesquisa, usado para encontrar grupos"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Vários"
+
#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Intervalo de tempo para verificar notificações (no topo)"
+
#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Intervalo de tempo de verificação entre duas notificações (no topo)"
+
#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Procurar novas versões"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Verifica automaticamente se existem novas versões"
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Idade máxima do registo no log"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "A idade maxima do registo de um log, em dias, e de"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Itens por página"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Número de itens apresentados por página"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Redirecionamento pré-definido"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr ""
"O redirecionamento padrão usado quando nenhuma aplicação se encontra "
"especificada"
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "A chave deve ter tamanho de 16, 24, ou 32 bytes"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Sintax inválida"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Número de linhas inválido"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Este campo é obrigatório"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Exibir"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Idioma preferido"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Idioma preferido para exibir páginas"
+
#: core/forms.py:14
msgid "Username"
msgstr "Nome de Utilizador"
+
#: core/forms.py:18
msgid "Password"
msgstr "Password"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Password antiga"
+
#: core/forms.py:33
msgid "New password"
msgstr "Nova password"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Confirmação"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Incompatibilidade da password antiga"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Passwords não coincidem"
+
#: core/models.py:52
msgid "password"
msgstr "password"
+
#: core/models.py:54
msgid "last login"
msgstr "último login"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Não pode apagar a sua própria conta"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Falha ao actualizar password: Modulo LDAP não instalado"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "conta"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Linha inválida"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "Não é possível importa uma conta com permissões superiores"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "O simple utilizador '%s' deve ter endereço de e-mail válido"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr ""
"Os campos nome de utilizador e endereço de email não deve ser diferente para "
"'%s'"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "acrescentado"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "modificado"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s pelo utilizador %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "apagado"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Extras"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Escolher a(s) extensões a usar "
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Nome"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Versão"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Descrição"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Informação"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Informações variadas sobre Modoboa"
+
#: core/templates/core/information.html:5
-msgid "An update is available!"
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "Uma nova versão está disponível!"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "está de momento em uso."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Autenticação"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Nome"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Último login"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Descrição"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Utilizadores ativos"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Nome do grupo"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Último login"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Logs"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Anteriormente no Modoboa..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Data"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Nível"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Logger"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Mensagem"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Parâmetros"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Configurar Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Guardar"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Definições do Modoboa"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Definições"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Preferências"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Personalizar Modoboa"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Perfil"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Atualizar o sua informação pessoal"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Actualizar"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Sair"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Benvindo ao Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Parâmetros salvos"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "O utilizador '%s' fez login com sucesso"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "O seu nome de utilizador"
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "O utilizador '%s' fez logout"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Perfil atualizado"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Preferências salvas"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Mensagens de teste"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Enviar vírus"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Enviar spam"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -465,93 +592,138 @@ msgstr ""
"seguinte link \n"
" mailing "
"list .\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Mensagem enviada"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "A ligação à base de dados %s não está devidamente configurada"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Acesso negado: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Acesso negado"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr "Enviar"
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Pedido inválido"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Introduzir um nome de domínio válido "
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Sim"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "Não"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Falha ao actualizar a password: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Utilizador simples"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super Administrador"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Administrador de domínio"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Lamentamos"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "A página solicitada não existe."
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Ocorreu um erro interno."
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Procurar..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Do endereço"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Assunto"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Ambos"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Erro:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Ajuda:"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Fechar"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Anterior"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Seguinte"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Benvindo ao Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Lembrar-me"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Entrar"
+
+#~ msgid "New Modoboa version available"
+#~ msgstr "Existem uma nova versão do Modoboa disponivel"
+
+#~ msgid "Extensions"
+#~ msgstr "Extras"
+
+#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Escolher a(s) extensões a usar "
+
+#~ msgid "Version"
+#~ msgstr "Versão"
+
+#~ msgid "is currently in use."
+#~ msgstr "está de momento em uso."
diff --git a/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po b/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po
index ecdac6a8b..e7ca97405 100644
--- a/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po
@@ -13,7 +13,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2014-12-29 12:08+0000\n"
"Last-Translator: Mike C. \n"
"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/"
@@ -23,24 +23,31 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Não há mais entradas do registo para mostrar"
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Aviso"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Cancelar"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr "Erro interno"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Não existem mais entradas a mostrar"
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Procurar"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Pesquisar..."
diff --git a/modoboa/locale/ru/LC_MESSAGES/django.po b/modoboa/locale/ru/LC_MESSAGES/django.po
index 351909c34..5c90dab18 100644
--- a/modoboa/locale/ru/LC_MESSAGES/django.po
+++ b/modoboa/locale/ru/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2013-12-03 09:35+0000\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: Russian (http://www.transifex.com/projects/p/modoboa/language/"
@@ -18,95 +18,126 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Основные"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr ""
+
+#: core/__init__.py:85
+#, fuzzy
+msgid "One or more updates are available"
+msgstr "Статистика не доступна"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Аутентификация"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Тип аутентификации"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Локальный"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Базовая программа для проверки подлинности"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Схема пароля по умолчанию"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr ""
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr ""
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr ""
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr ""
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr ""
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Схема используемая для шифровании пароля почтового ящика."
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr ""
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
"between 1000 and 999999999, inclusive."
msgstr ""
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Секретный ключ"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Ключ для шифрования паролей"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "Параметры LDAP"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Адрес сервера"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "IP адрес или DNS имя сервера LDAP"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Порт сервера"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "Номер TCP порта LDAP сервера"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Использовать безопасное соединение"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Использовать SSL/TLS соединение с LDAP сервером"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Метод аутентификации"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Найти и соединиться"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Прямое соединение"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Выберите метод аутентификации "
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Соединится с DN "
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -114,21 +145,27 @@ msgid ""
msgstr ""
"Отличительное имя используемое для соединения с LDAP сервером. Оставьте "
"пустым для анонимного соединения"
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Пароль для соединения"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr "Пароль для соединения с LDAP сервером"
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr ""
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr ""
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Фильтр поиска"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -136,9 +173,11 @@ msgid ""
msgstr ""
"Необязательная срока поиска (например '(objectClass=person)') Значение нужно "
"заключить в скобки"
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Шаблон пользователя DN"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -147,286 +186,371 @@ msgid ""
msgstr ""
"Шаблон используется для построения запросов к DN Он должен содержать атрибут "
"например (%(user)s)"
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Свойства пароля"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Свойства используемые для сохранения пользовательских паролей"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Укажите, если LDAP сервер в Active Directory"
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr ""
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
"Use ';' characters to separate groups."
msgstr ""
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr ""
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr ""
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Прочее"
+
#: core/app_settings.py:201
#, fuzzy
msgid "Top notifications check interval"
msgstr "Уведомления отправителю"
+
#: core/app_settings.py:203
#, fuzzy
msgid "Interval between two top notification checks"
msgstr "Интервал между запросами на деблокирование для доставки"
+
#: core/app_settings.py:208
#, fuzzy
msgid "Check new versions"
msgstr "Отметить для разрешения этого расширения"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr ""
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Максимальный срок хранения лог записей"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "Срок хранения лог записей в днях "
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Элементов на странице"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Количество элементов на странице"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Порог перенаправления по умолчанию"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr "Если приложение не указано. Используется перенаправление по умолчанию."
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Ключ должен быть 16, 24 или 32 байта длинной"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Ошибка в написании"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr ""
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Это поле обязательно для заполнеия"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Отображение"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Предпочитаемый язык"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Предпочитаемый язык для отображения страниц"
+
#: core/forms.py:14
msgid "Username"
msgstr "Логин пользователя"
+
#: core/forms.py:18
msgid "Password"
msgstr "Пароль"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Старый пароль"
+
#: core/forms.py:33
msgid "New password"
msgstr "Новый пароль"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Подтверждение"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Старые пароли не совпадают"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Пароли не совпадают"
+
#: core/models.py:52
msgid "password"
msgstr ""
+
#: core/models.py:54
msgid "last login"
msgstr ""
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Вы не можете удалить собственный аккаунт"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Ошибка обновления пароля: модуль LDAP не установлен"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "Аккаунт"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Ошибочная строка"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "Вы не можете импортировать аккаунт с ролью старше чем у вас"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "Пользователь '%s' должен иметь действительный почтовый адрес"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "Имя пользователя и адрес не должны отличатся для пользователя '%s'"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "добавлено"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "изменено"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s пользователем %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "удалено"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Расширения"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Выберите расширения для использования"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Логин"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Версия"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Описание"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Информация"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Различная информация о Modoboa"
+
#: core/templates/core/information.html:5
#, fuzzy
-msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "Статистика не доступна"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "используется в настоящее время"
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Аутентификация"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Логин"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Последний вход"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Описание"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Активные пользователи"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Название группы"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Последний вход"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Логи"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Ранее в Modoboa ..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Дата"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Уровень"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Логгер"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Сообщение"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Параметры"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Настройка Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Сохранить"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Настройки Modoboa"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Настройки"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Параметры"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Настроить Modoboa"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Профиль"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Обновить личную информацию"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Обновление"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Завершить сеанс"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Добро пожаловать в Modoboa!"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Параметры сохранены"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Пользователь '%s' успешно вошел в систему"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "Не правильное имя или пароль. Попробуйте еще раз."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Пользователь '%s' вышел из системы"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Профиль обновлен"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Параметры сохранены"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Тестовое сообщение"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Отправить вирус"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Отправить спам"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -456,132 +580,135 @@ msgstr ""
"По любым вопросам и с предложениями обращайтесь пожалуйста\n"
" Список "
"рассылки .
\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Сообщение отправлено"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr ""
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "В разрешении отказано: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "В разрешении отказано"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr ""
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Ошибочный запрос"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Введите действительный адрес домена"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Да"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "Нет"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Ошибка обновления пароля: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Обычный пользователь"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Супер администратор"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Администратор домена"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Жаль"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "Запрошенная станица не существует"
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Внутренняя ошибка"
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Поиск..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Адрес отправителя"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Тема"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Оба"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Ошибка:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Подсказка:"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Закрыть"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Предыдущая"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Следующая"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Добро пожаловать в Modoboa!"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Запомнить меня"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Войти"
+
+#~ msgid "Extensions"
+#~ msgstr "Расширения"
+
#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
-#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Выберите расширения для использования"
+
+#~ msgid "Version"
+#~ msgstr "Версия"
+
+#~ msgid "is currently in use."
+#~ msgstr "используется в настоящее время"
diff --git a/modoboa/locale/ru/LC_MESSAGES/djangojs.po b/modoboa/locale/ru/LC_MESSAGES/djangojs.po
index f892f590e..089fe32ff 100644
--- a/modoboa/locale/ru/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/ru/LC_MESSAGES/djangojs.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2013-12-03 09:35+0000\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: Russian (http://www.transifex.com/projects/p/modoboa/language/"
@@ -18,26 +18,31 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr ""
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Внимание"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Отмена"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr ""
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr ""
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Поиск"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Поиск..."
-#, fuzzy
-#, fuzzy
diff --git a/modoboa/locale/sv/LC_MESSAGES/django.po b/modoboa/locale/sv/LC_MESSAGES/django.po
index 3dcee91d4..0084afa6c 100644
--- a/modoboa/locale/sv/LC_MESSAGES/django.po
+++ b/modoboa/locale/sv/LC_MESSAGES/django.po
@@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:06+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2015-01-13 15:18+0000\n"
"Last-Translator: Olle Gustafsson \n"
"Language-Team: Swedish (http://www.transifex.com/projects/p/modoboa/language/"
@@ -20,48 +20,65 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/__init__.py:65 core/__init__.py:66
msgid "General"
msgstr "Generellt"
-#: core/__init__.py:84
-msgid "New Modoboa version available"
-msgstr "En ny version av Modoboa är tillgänglig"
+
+#: core/__init__.py:85
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available"
+msgstr "En uppdatering finns tillgänglig!"
+
#: core/app_settings.py:34
msgid "Authentication"
msgstr "Autentisering"
+
#: core/app_settings.py:37
msgid "Authentication type"
msgstr "Autentiseringstyp"
+
#: core/app_settings.py:38
msgid "Local"
msgstr "Lokal"
+
#: core/app_settings.py:41
msgid "The backend used for authentication"
msgstr "Autentiserings backend"
+
#: core/app_settings.py:46
msgid "Default password scheme"
msgstr "Standard lösenords schema"
+
#: core/app_settings.py:49
msgid "md5crypt (weak)"
msgstr "md5crypt (svag)"
+
#: core/app_settings.py:50
msgid "sha256 (weak)"
msgstr "sha256 (svag)"
+
#: core/app_settings.py:51
msgid "md5 (weak)"
msgstr "md5 (svag)"
+
#: core/app_settings.py:52
msgid "crypt (weak)"
msgstr "crypt (svag)"
+
#: core/app_settings.py:53
msgid "plain (weak)"
msgstr "okrypterad (svag)"
+
#: core/app_settings.py:55
msgid "Scheme used to crypt mailbox passwords"
msgstr "Krypteringsschema för brevlåde lösenord"
+
#: core/app_settings.py:60
msgid "Rounds"
msgstr "Antal omgångar"
+
#: core/app_settings.py:63
msgid ""
"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be "
@@ -69,48 +86,63 @@ msgid ""
msgstr ""
"Antal omgångar att använda (används endast av sha256crypt och sha512crypt). "
"Måste vara mellan 1000 och 999999999."
+
#: core/app_settings.py:70
msgid "Secret key"
msgstr "Hemlig nyckel"
+
#: core/app_settings.py:72
msgid "Key used to encrypt/decrypt passwords"
msgstr "Nyckel som används för att kryptera / dekryptera lösenord"
+
#: core/app_settings.py:77
msgid "LDAP settings"
msgstr "LDAP inställningar"
+
#: core/app_settings.py:80
msgid "Server address"
msgstr "Server adress"
+
#: core/app_settings.py:83
msgid "The IP address of the DNS name of the LDAP server"
msgstr "IP adressen eller DNS namn för LDAP server"
+
#: core/app_settings.py:88
msgid "Server port"
msgstr "Server port"
+
#: core/app_settings.py:90
msgid "The TCP port number used by the LDAP server"
msgstr "TCP port som används av LDAP servern"
+
#: core/app_settings.py:95
msgid "Use a secured connection"
msgstr "Använd en säker anslutning"
+
#: core/app_settings.py:98
msgid "Use an SSL/TLS connection to access the LDAP server"
msgstr "Använd SSL/TLS anslutning för åtkomst till LDAP servern"
+
#: core/app_settings.py:102
msgid "Authentication method"
msgstr "Autentiseringsmetod"
+
#: core/app_settings.py:103
msgid "Search and bind"
msgstr "Sök och bind"
+
#: core/app_settings.py:104
msgid "Direct bind"
msgstr "Direkt bindning"
+
#: core/app_settings.py:106
msgid "Choose the authentication method to use"
msgstr "Välj autentiseringsmetod att använda"
+
#: core/app_settings.py:111
msgid "Bind DN"
msgstr "Bind DN"
+
#: core/app_settings.py:114
msgid ""
"The distinguished name to use when binding to the LDAP server. Leave empty "
@@ -118,22 +150,28 @@ msgid ""
msgstr ""
"Det unika namnet för att använda vid bindningar till LDAP-servern. Lämna "
"tomt för en anonym bindning"
+
#: core/app_settings.py:122
msgid "Bind password"
msgstr "Bind lösenord"
+
#: core/app_settings.py:125
msgid "The password to use when binding to the LDAP server (with 'Bind DN')"
msgstr ""
"Lösenordet ska användas vid bindning till LDAP-servern (med \"Bind DN ')"
+
#: core/app_settings.py:134
msgid "Users search base"
msgstr "Användare sökbas"
+
#: core/app_settings.py:137
msgid "The distinguished name of the search base used to find users"
msgstr "Det unika namnet för sökbasen som används för att hitta användare"
+
#: core/app_settings.py:144
msgid "Search filter"
msgstr "Sökfilter"
+
#: core/app_settings.py:147
msgid ""
"An optional filter string (e.g. '(objectClass=person)'). In order to be "
@@ -141,9 +179,11 @@ msgid ""
msgstr ""
"En valfri filtersträng (t.ex. \"(objectClass = personer) '). För att vara "
"giltigt måste det omges av parenteser."
+
#: core/app_settings.py:155
msgid "User DN template"
msgstr "Anvädar DN mall"
+
#: core/app_settings.py:158
#, python-format
msgid ""
@@ -152,21 +192,27 @@ msgid ""
msgstr ""
"Mallen som används för att konstruera en användares DN. Den bör innehålla en "
"platshållare (dvs. %(user)s)"
+
#: core/app_settings.py:166
msgid "Password attribute"
msgstr "Lösenordsattribut"
+
#: core/app_settings.py:168
msgid "The attribute used to store user passwords"
msgstr "Attribut som används för att lagra användarlösenord"
+
#: core/app_settings.py:173
msgid "Active Directory"
msgstr "Active Directory"
+
#: core/app_settings.py:176
msgid "Tell if the LDAP server is an Active Directory one"
msgstr "Berätta om LDAP-servern är en Active Directory"
+
#: core/app_settings.py:180
msgid "Administrator groups"
msgstr "Administratörsgrupper"
+
#: core/app_settings.py:183
msgid ""
"Members of those LDAP Posix groups will be created as domain administrators. "
@@ -174,266 +220,343 @@ msgid ""
msgstr ""
"Användare av dessa LDAP Posix grupper kommer skapas som "
"domänadministratörer. Använd ';' för att separera grupper."
+
#: core/app_settings.py:190
msgid "Groups search base"
msgstr "Grupper sökbas"
+
#: core/app_settings.py:193
msgid "The distinguished name of the search base used to find groups"
msgstr "Det unika namnet för sökbasen som används för att hitta grupper"
+
#: core/app_settings.py:198
msgid "Miscellaneous"
msgstr "Övrigt"
+
#: core/app_settings.py:201
msgid "Top notifications check interval"
msgstr "Toppnotifikationer kontrollintervall"
+
#: core/app_settings.py:203
msgid "Interval between two top notification checks"
msgstr "Intervall mellan två toppnotifikation kontroller"
+
#: core/app_settings.py:208
msgid "Check new versions"
msgstr "Kontrollera nya versioner"
+
#: core/app_settings.py:211
msgid "Automatically checks if a newer version is available"
msgstr "Kontrollera automatiskt om en nyare version finns"
+
#: core/app_settings.py:215
msgid "Maximum log record age"
msgstr "Maximal ålder för loggpost"
+
#: core/app_settings.py:217
msgid "The maximum age in days of a log record"
msgstr "Maximal ålder i dagar för en logg post"
+
#: core/app_settings.py:222
msgid "Items per page"
msgstr "Artiklar per sida"
+
#: core/app_settings.py:224
msgid "Number of displayed items per page"
msgstr "Antal poster som visas per sida"
+
#: core/app_settings.py:229
msgid "Default top redirection"
msgstr "Standard topp omdirigering"
+
#: core/app_settings.py:233
msgid "The default redirection used when no application is specified"
msgstr "Standard omdirigering när ingen applikation angetts"
+
#: core/app_settings.py:263
msgid "Key must be either 16, 24, or 32 bytes long"
msgstr "Nyckel måste vara endera 16, 24 eller 32 bytes lång"
+
#: core/app_settings.py:272
msgid "Invalid syntax"
msgstr "Ogiltig syntax"
+
#: core/app_settings.py:278
msgid "Invalid rounds number"
msgstr "Ogiltigt antal omgångar"
+
#: core/app_settings.py:299
msgid "This field is required"
msgstr "Detta fält är obligatoriskt"
+
#: core/app_settings.py:367
msgid "Display"
msgstr "Visning"
+
#: core/app_settings.py:371
msgid "Prefered language"
msgstr "Önskat språk"
+
#: core/app_settings.py:383
msgid "Prefered language to display pages"
msgstr "Önskat språk för att visa sidor"
+
#: core/forms.py:14
msgid "Username"
msgstr "Användarnamn"
+
#: core/forms.py:18
msgid "Password"
msgstr "Lösenord"
+
#: core/forms.py:29
msgid "Old password"
msgstr "Gammalt lösenord"
+
#: core/forms.py:33
msgid "New password"
msgstr "Nytt lösenord"
+
#: core/forms.py:37
msgid "Confirmation"
msgstr "Bekräftelse"
+
#: core/forms.py:64
msgid "Old password mismatchs"
msgstr "Gammalt lösenord matchar inte"
+
#: core/forms.py:71
msgid "Passwords mismatch"
msgstr "Lösenord matchar inte"
+
#: core/models.py:52
msgid "password"
msgstr "lösenord"
+
#: core/models.py:54
msgid "last login"
msgstr "senaste inloggning"
+
#: core/models.py:83
msgid "You can't delete your own account"
msgstr "Du kan inte radera ditt eget konto"
-#: core/models.py:132
+
+#: core/models.py:133
msgid "Failed to update password: LDAP module not installed"
msgstr "Misslyckades med att uppdatera lösenord: LDAP modul ej installerad"
-#: core/models.py:185
+
+#: core/models.py:186
msgid "account"
msgstr "konto"
-#: core/models.py:338
+
+#: core/models.py:339
msgid "Invalid line"
msgstr "Ogiltig rad"
-#: core/models.py:343
+
+#: core/models.py:344
msgid "You can't import an account with a role greater than yours"
msgstr "Du kan inte importera konto med en roll större än din"
-#: core/models.py:355
+
+#: core/models.py:356
#, python-format
msgid "The simple user '%s' must have a valid email address"
msgstr "Den enkla användaren '%s' måste ha en gällande e-postadress"
-#: core/models.py:360
+
+#: core/models.py:361
#, python-format
msgid "username and email fields must not differ for '%s'"
msgstr "användarnamn och e-post fält får inte avvika för '%s'"
-#: core/models.py:461
+
+#: core/models.py:462
msgid "added"
msgstr "tillagd"
-#: core/models.py:464
+
+#: core/models.py:465
msgid "modified"
msgstr "ändrad"
-#: core/models.py:466 core/models.py:491
+
+#: core/models.py:467 core/models.py:492
#, python-format
msgid "%(object)s '%(name)s' %(action)s by user %(user)s"
msgstr "%(object)s '%(name)s' %(action)s av användare %(user)s"
-#: core/models.py:493
+
+#: core/models.py:494
msgid "deleted"
msgstr "raderad"
-#: core/templates/core/extensions.html:4 core/templatetags/core_tags.py:52
-msgid "Extensions"
-msgstr "Tillägg"
-#: core/templates/core/extensions.html:4
-#, fuzzy
-#| msgid "Choose the extension(s) to use"
-msgid "The extension(s) you are using"
-msgstr "Välj tillägg att aktivera"
-#: core/templates/core/extensions.html:8
-#: core/templates/core/information.html:16
-msgid "Name"
-msgstr "Namn"
-#: core/templates/core/extensions.html:9
-msgid "Version"
-msgstr "Version"
-#: core/templates/core/extensions.html:10
-msgid "Description"
-msgstr "Beskrivning"
-#: core/templates/core/information.html:2 core/templatetags/core_tags.py:57
+
+#: core/templates/core/information.html:2 core/templatetags/core_tags.py:52
msgid "Information"
msgstr "Information"
+
#: core/templates/core/information.html:2
msgid "Various information about Modoboa"
msgstr "Uppgifter om Modoboa"
+
#: core/templates/core/information.html:5
-msgid "An update is available!"
+#, fuzzy
+#| msgid "An update is available!"
+msgid "One or more updates are available!"
msgstr "En uppdatering finns tillgänglig!"
+
#: core/templates/core/information.html:6
-#, python-format
-msgid ""
-"\n"
-" Modoboa %(version)s is available for download. The list "
-"of all changes is available here .\n"
-" "
+msgid "Check the following list to find the component(s) that can be updated."
msgstr ""
-"\n"
-" Modoboa %(version)s finsn för nedladdning. Lista över "
-"förändringar finns här .\n"
-" "
-#: core/templates/core/information.html:11
-msgid "is currently in use."
-msgstr "används för närvarande."
-#: core/templates/core/information.html:13
+
+#: core/templates/core/information.html:10
+#, fuzzy
+#| msgid "Authentication"
+msgid "Applications"
+msgstr "Autentisering"
+
+#: core/templates/core/information.html:14
+#: core/templates/core/information.html:36
+msgid "Name"
+msgstr "Namn"
+
+#: core/templates/core/information.html:15
+msgid "Installed version"
+msgstr ""
+
+#: core/templates/core/information.html:16
+#, fuzzy
+#| msgid "Last login"
+msgid "Last version"
+msgstr "Senaste inloggad"
+
+#: core/templates/core/information.html:17
+msgid "Description"
+msgstr "Beskrivning"
+
+#: core/templates/core/information.html:32
msgid "Active users"
msgstr "Aktiva användare"
-#: core/templates/core/information.html:17
+
+#: core/templates/core/information.html:37
msgid "Group name"
msgstr "Gruppnamn"
-#: core/templates/core/information.html:18
+
+#: core/templates/core/information.html:38
msgid "Last login"
msgstr "Senaste inloggad"
-#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:61
+
+#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:56
msgid "Logs"
msgstr "Loggar"
+
#: core/templates/core/logs.html:2
msgid "Previously on Modoboa..."
msgstr "Tidigare på Modoboa..."
+
#: core/templates/core/logs.html:6
msgid "Date"
msgstr "Datum"
+
#: core/templates/core/logs.html:7
msgid "Level"
msgstr "Nivå"
+
#: core/templates/core/logs.html:8
msgid "Logger"
msgstr "Loggare"
+
#: core/templates/core/logs.html:9
msgid "Message"
msgstr "Meddelande"
-#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:66
+
+#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:61
msgid "Parameters"
msgstr "Parametrar"
+
#: core/templates/core/parameters.html:2
msgid "Configure Modoboa"
msgstr "Konfigurera Modoboa"
+
#: core/templates/core/parameters.html:6
#: core/templates/core/user_preferences.html:8
msgid "Save"
msgstr "Spara"
+
#: core/templates/core/settings_header.html:5
msgid "Modoboa settings"
msgstr "Modoboa inställningar"
-#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:85
+
+#: core/templates/core/user_index.html:4 core/templatetags/core_tags.py:80
msgid "Settings"
msgstr "Inställningar"
+
#: core/templates/core/user_preferences.html:2
-#: core/templatetags/core_tags.py:112
+#: core/templatetags/core_tags.py:107
msgid "Preferences"
msgstr "Inställningar"
+
#: core/templates/core/user_preferences.html:2
msgid "Customize Modoboa"
msgstr "Anpassa Modoboa"
-#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:108
+
+#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:103
msgid "Profile"
msgstr "Profil"
+
#: core/templates/core/user_profile.html:2
msgid "Update your personal information"
msgstr "Uppdatera personlig information"
+
#: core/templates/core/user_profile.html:8 lib/form_utils.py:333
msgid "Update"
msgstr "Uppdatera"
+
#: core/templatetags/core_tags.py:25
msgid "Modoboa"
msgstr "Modoboa"
-#: core/templatetags/core_tags.py:94
+
+#: core/templatetags/core_tags.py:89
msgid "Logout"
msgstr "Logga ut"
-#: core/views/admin.py:51
+
+#: core/utils.py:20
+#, fuzzy
+#| msgid "Welcome to Modoboa"
+msgid "The core part of Modoboa"
+msgstr "Välkommen till Modoboa"
+
+#: core/views/admin.py:52
msgid "Parameters saved"
msgstr "Parametrar sparade"
+
#: core/views/auth.py:33
#, python-format
msgid "User '%s' successfully logged in"
msgstr "Användare '%s' har loggat in"
+
#: core/views/auth.py:48
msgid "Your username and password didn't match. Please try again."
msgstr "Ditt användarnamn och lösenord matchar inte. Var vänlig försök igen."
+
#: core/views/auth.py:76
#, python-format
msgid "User '%s' logged out"
msgstr "Användare '%s' har loggat ut"
+
#: core/views/user.py:39
msgid "Profile updated"
msgstr "Profil uppdaterad"
+
#: core/views/user.py:62
msgid "Preferences saved"
msgstr "Inställningar sparade"
+
#: demo/__init__.py:17
msgid "Test messages"
msgstr "Test meddelande"
+
#: demo/__init__.py:22
msgid "Send virus"
msgstr "Skicka virus"
+
#: demo/__init__.py:25
msgid "Send spam"
msgstr "Skicka skräppost"
+
#: demo/templates/demo/login_announcement.html:2
msgid ""
"\n"
@@ -463,93 +586,151 @@ msgstr ""
"Var vänlig rapportera eventuella fel eller ge förslag på mailinglistan ."
"
\n"
+
#: demo/views.py:19 demo/views.py:45
msgid "Message sent"
msgstr "Meddelande sänt"
+
#: lib/db_utils.py:39
#, python-format
msgid "Connection to database %s not configured"
msgstr "Anslutning till databasen %s är inte konfigurerad"
+
#: lib/exceptions.py:67
#, python-format
msgid "Permission denied: %s"
msgstr "Tillstånd nekas: %s"
+
#: lib/exceptions.py:68
msgid "Permission denied"
msgstr "Tillstånd nekas"
+
#: lib/form_utils.py:88
msgid "Submit"
msgstr "Skicka"
+
#: lib/form_utils.py:124 lib/form_utils.py:127
msgid "Invalid request"
msgstr "Ogiltig förfrågan"
-#: lib/form_utils.py:358 lib/form_utils.py:366
+
+#: lib/form_utils.py:360 lib/form_utils.py:368
msgid "Enter a valid domain name"
msgstr "Skriv in ett giltigt domännamn"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "Yes"
msgstr "Ja"
-#: lib/form_utils.py:415
+
+#: lib/form_utils.py:417
msgid "No"
msgstr "Nej"
+
#: lib/ldap_utils.py:116
#, python-format
msgid "Failed to update password: %s"
msgstr "Misslyckades med att uppdatera lösenord: %s"
+
#: lib/permissions.py:22
msgid "Simple user"
msgstr "Enkel användare"
+
#: lib/permissions.py:24
msgid "Super administrator"
msgstr "Super administratör"
+
#: lib/permissions.py:30
msgid "Domain administrator"
msgstr "Domän administratör"
+
#: templates/404.html:4 templates/500.html:4
msgid "Sorry"
msgstr "Ursäkta"
+
#: templates/404.html:5
msgid "The requested page does not exist."
msgstr "Den begärda sidan finns inte."
+
#: templates/500.html:5
msgid "An internal error occured."
msgstr "Ett internt fel uppstod."
+
#: templates/common/email_searchbar.html:5
msgid "Search..."
msgstr "Sök..."
+
#: templates/common/email_searchbar.html:10
msgid "From address"
msgstr "Från adress"
+
#: templates/common/email_searchbar.html:17
msgid "Subject"
msgstr "Ämne"
+
#: templates/common/email_searchbar.html:33
msgid "Both"
msgstr "Båda"
+
#: templates/common/error.html:4
msgid "Error:"
msgstr "Fel:"
+
#: templates/common/generic_field.html:11
#: templates/common/generic_fields_group.html:8
msgid "Help:"
msgstr "Hjälp:"
+
#: templates/common/generic_modal.html:6
#: templates/common/generic_modal.html:13 templates/common/wizard_forms.html:6
#: templates/common/wizard_forms.html:27
msgid "Close"
msgstr "Stäng"
+
#: templates/common/wizard_forms.html:31
msgid "Previous"
msgstr "Föregående"
+
#: templates/common/wizard_forms.html:32
msgid "Next"
msgstr "Nästa"
-#: templates/registration/login.html:8
+
+#: templates/registration/login.html:10
msgid "Welcome to Modoboa"
msgstr "Välkommen till Modoboa"
-#: templates/registration/login.html:39
+
+#: templates/registration/login.html:41
msgid "Remember me"
msgstr "Kom ihåg mig"
-#: templates/registration/login.html:42
+
+#: templates/registration/login.html:44
msgid "Log in"
msgstr "Logga in"
+
+#~ msgid "New Modoboa version available"
+#~ msgstr "En ny version av Modoboa är tillgänglig"
+
+#~ msgid "Extensions"
+#~ msgstr "Tillägg"
+
+#, fuzzy
+#~| msgid "Choose the extension(s) to use"
+#~ msgid "The extension(s) you are using"
+#~ msgstr "Välj tillägg att aktivera"
+
+#~ msgid "Version"
+#~ msgstr "Version"
+
+#~ msgid ""
+#~ "\n"
+#~ " Modoboa %(version)s is available for download. The "
+#~ "list of all changes is available here .\n"
+#~ " "
+#~ msgstr ""
+#~ "\n"
+#~ " Modoboa %(version)s finsn för nedladdning. Lista över "
+#~ "förändringar finns här"
+#~ "a>.\n"
+#~ " "
+
+#~ msgid "is currently in use."
+#~ msgstr "används för närvarande."
diff --git a/modoboa/locale/sv/LC_MESSAGES/djangojs.po b/modoboa/locale/sv/LC_MESSAGES/djangojs.po
index a1dbe3432..b151e47e1 100644
--- a/modoboa/locale/sv/LC_MESSAGES/djangojs.po
+++ b/modoboa/locale/sv/LC_MESSAGES/djangojs.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Modoboa\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-11 15:07+0100\n"
+"POT-Creation-Date: 2015-04-08 15:58+0200\n"
"PO-Revision-Date: 2015-01-13 15:21+0000\n"
"Last-Translator: Olle Gustafsson \n"
"Language-Team: Swedish (http://www.transifex.com/projects/p/modoboa/language/"
@@ -19,24 +19,31 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
#: core/static/core/js/settings.js:14
msgid "No more log entry to show"
msgstr "Inga fler logg poster att visa"
+
#: static/js/confirmation.js:44
msgid "Warning"
msgstr "Varning"
+
#: static/js/confirmation.js:59
msgid "Cancel"
msgstr "Avbryt"
+
#: static/js/global.js:329
msgid "Internal error"
msgstr "Internt fel"
+
#: static/js/listing.js:21
msgid "No more entry to show"
msgstr "Inga fler poster att visa"
+
#: static/js/listing.js:46
msgid "Search"
msgstr "Sök"
+
#: static/js/searchbar.js:28
msgid "Search..."
msgstr "Sök..."
From db9b24beb0fee6747cb9aec0142932cbe3a1546f Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Wed, 8 Apr 2015 16:05:53 +0200
Subject: [PATCH 23/25] Documentation update
---
doc/integration/imap_and_smtp.rst | 2 +-
modoboa/core/commands/postfix_maps.py | 9 ++++++++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/doc/integration/imap_and_smtp.rst b/doc/integration/imap_and_smtp.rst
index cfcd02ab4..be670a535 100644
--- a/doc/integration/imap_and_smtp.rst
+++ b/doc/integration/imap_and_smtp.rst
@@ -422,7 +422,7 @@ be used by Postfix to lookup into Modoboa tables.
To automaticaly generate the requested map files and store them in a
directory, run the following command::
- $ modoboa-admin.py postfix_maps --dbtype --extensions
+ $ modoboa-admin.py postfix_maps --dbtype --extensions all
```` is the directory where the files will be
stored. Answer the few questions and you're done.
diff --git a/modoboa/core/commands/postfix_maps.py b/modoboa/core/commands/postfix_maps.py
index f10c6e111..ddcbed991 100644
--- a/modoboa/core/commands/postfix_maps.py
+++ b/modoboa/core/commands/postfix_maps.py
@@ -11,6 +11,7 @@ from django.template import Context, Template
import dj_database_url
+from modoboa.lib.api_client import ModoAPIClient
from . import Command
MAP_FILE_TEMPLATE = """user = {{ dbuser }}
@@ -85,8 +86,11 @@ class MapFilesGenerator(object):
"""Load specified extensions."""
if "all" in extensions:
# Retrieve extension list from the API
- return
+ official_exts = ModoAPIClient().list_extensions()
+ extensions = [extension["name"] for extension in official_exts]
+
for extension in extensions:
+ extension = extension.replace("-", "_")
try:
__import__(extension, locals(), globals(), ["postfix_maps"])
except ImportError:
@@ -126,6 +130,9 @@ query = {{ query|safe }}
class PostfixMapsCommand(Command):
+
+ """Base command to generate map files."""
+
help = "Generate ready-to-use postfix map files"
def __init__(self, *args, **kwargs):
From a6f34bd00961e7de4e6d7e78162acf9fd2271b67 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Thu, 9 Apr 2015 17:24:51 +0200
Subject: [PATCH 24/25] Adding comments.
---
modoboa/lib/tests.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/modoboa/lib/tests.py b/modoboa/lib/tests.py
index ade238400..f8a410c31 100644
--- a/modoboa/lib/tests.py
+++ b/modoboa/lib/tests.py
@@ -13,6 +13,8 @@ from modoboa.lib import parameters
class ModoTestCase(TestCase):
+ """All test cases must inherit from this one."""
+
def setUp(self, username="admin", password="password"):
management.call_command("load_initial_data")
self.clt = Client()
From cc4d60e4798e89cc1eaa847823aa3e54464c41a1 Mon Sep 17 00:00:00 2001
From: Antoine Nguyen
Date: Fri, 10 Apr 2015 15:13:47 +0200
Subject: [PATCH 25/25] Move DomainAdmins references (almost all) inside
modoboa_admin.
---
doc/extending/events.rst | 9 ++--
modoboa/core/__init__.py | 5 ---
modoboa/core/extensions.py | 41 +++++++++++--------
.../management/commands/load_initial_data.py | 2 +-
modoboa/core/models.py | 7 +++-
modoboa/lib/permissions.py | 9 +---
6 files changed, 38 insertions(+), 35 deletions(-)
diff --git a/doc/extending/events.rst b/doc/extending/events.rst
index 8b780d4a6..5d4964a2a 100644
--- a/doc/extending/events.rst
+++ b/doc/extending/events.rst
@@ -619,14 +619,16 @@ name, the model name and the permission name. Example::
GetExtraRoles
=============
-Let extensions define new administrative roles.
+Let extensions define new administrative roles (will be used to create
+or modify an account).
*Callback prototype*::
- def callback(user): pass
+ def callback(user, account): pass
* ``user`` is a ``User`` instance corresponding to the currently
logged in user
+* ``account`` is the account being modified (None on creation)
Callbacks listening to this event must return a list of 2uple (two
strings) which respect the following format: ``(value, label)``.
@@ -922,11 +924,12 @@ account.
*Callback prototype*::
- def callback(account, role): pass
+ def callback(user, role, account): pass
* ``user`` is the ``User`` instance corresponding to the currently
logged in user
* ``role`` is the role ``user`` tries to set
+* ``account`` is the account being modified (None on creation)
Must return a list containing ``True`` or ``False`` to indicate if
this user can is allowed to set ``role``.
diff --git a/modoboa/core/__init__.py b/modoboa/core/__init__.py
index 210c9f167..9da184959 100644
--- a/modoboa/core/__init__.py
+++ b/modoboa/core/__init__.py
@@ -45,11 +45,6 @@ BASE_EVENTS = [
]
PERMISSIONS = {
- "DomainAdmins": [
- ["core", "user", "add_user"],
- ["core", "user", "change_user"],
- ["core", "user", "delete_user"],
- ],
"SimpleUsers": []
}
diff --git a/modoboa/core/extensions.py b/modoboa/core/extensions.py
index 6037c1cd8..6b84ce3dc 100644
--- a/modoboa/core/extensions.py
+++ b/modoboa/core/extensions.py
@@ -75,6 +75,28 @@ class ExtensionsPool(object):
return None
return instance.infos()
+ def load_extension(self, name):
+ """Load a registered extension."""
+ __import__(name, locals(), globals(), ["modo_extension"])
+ extinstance = self.get_extension(name)
+ if extinstance is None:
+ return None
+ result = None
+ try:
+ baseurl = (
+ extinstance.url if extinstance.url is not None
+ else name
+ )
+ result = (
+ r'^%s/' % (baseurl),
+ include("{0}.urls".format(name), namespace=name)
+ )
+ except ImportError:
+ # No urls for this extension
+ pass
+ extinstance.load()
+ return result
+
def load_all(self):
"""Load all defined extensions.
@@ -88,22 +110,9 @@ class ExtensionsPool(object):
"""
result = []
for ext in settings.MODOBOA_APPS:
- __import__(ext, locals(), globals(), ["modo_extension"])
- extname = ext.split('.')[-1]
- extinstance = self.get_extension(extname)
- if extinstance is None:
- continue
- try:
- baseurl = extinstance.url \
- if extinstance.url is not None else extname
- result += [
- (r'^%s/' % (baseurl),
- include("{0}.urls".format(ext), namespace=extname))
- ]
- except ImportError:
- # No urls for this extension
- pass
- extinstance.load()
+ ext_urls = self.load_extension(ext)
+ if ext_urls is not None:
+ result += [ext_urls]
return result
def list_all(self, check_new_versions=False):
diff --git a/modoboa/core/management/commands/load_initial_data.py b/modoboa/core/management/commands/load_initial_data.py
index 341d3f376..e8cdd8229 100644
--- a/modoboa/core/management/commands/load_initial_data.py
+++ b/modoboa/core/management/commands/load_initial_data.py
@@ -38,7 +38,7 @@ class Command(BaseCommand, CloseConnectionMixin):
superadmin = User.objects.filter(is_superuser=True).first()
groups = PERMISSIONS.keys() + [
role[0] for role
- in events.raiseQueryEvent("GetExtraRoles", superadmin)
+ in events.raiseQueryEvent("GetExtraRoles", superadmin, None)
]
for groupname in groups:
group, created = Group.objects.get_or_create(name=groupname)
diff --git a/modoboa/core/models.py b/modoboa/core/models.py
index 80b77bb15..811d2246e 100644
--- a/modoboa/core/models.py
+++ b/modoboa/core/models.py
@@ -335,11 +335,14 @@ class User(PermissionsMixin):
:param row: a list containing the expected information
:param crypt_password:
"""
+ from modoboa.lib.permissions import get_account_roles
+
if len(row) < 7:
raise BadRequest(_("Invalid line"))
+ allowed_roles = get_account_roles(user)
+ allowed_roles = [role[0] for role in allowed_roles]
role = row[6].strip()
- allowed_roles = ["SimpleUsers", "DomainAdmins"]
- if not user.is_superuser and role not in allowed_roles:
+ if role not in allowed_roles:
raise PermDeniedException(
_("You can't import an account with a role greater than yours")
)
diff --git a/modoboa/lib/permissions.py b/modoboa/lib/permissions.py
index c993c2b04..fe5fd62e1 100644
--- a/modoboa/lib/permissions.py
+++ b/modoboa/lib/permissions.py
@@ -2,7 +2,6 @@
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
-from django.db import IntegrityError
from django.utils.translation import ugettext as _
from modoboa.core.models import ObjectAccess, User
@@ -22,13 +21,7 @@ def get_account_roles(user, account=None):
std_roles = [("SimpleUsers", _("Simple user"))]
if user.is_superuser:
std_roles += [("SuperAdmins", _("Super administrator"))]
- filters = events.raiseQueryEvent(
- 'UserCanSetRole', user, 'DomainAdmins', account
- )
- if user.has_perm("admin.add_domain") and \
- (not filters or True in filters):
- std_roles += [("DomainAdmins", _("Domain administrator"))]
- std_roles += events.raiseQueryEvent("GetExtraRoles", user)
+ std_roles += events.raiseQueryEvent("GetExtraRoles", user, account)
return sorted(std_roles, key=lambda role: role[1])