mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
+1
-1
@@ -16,7 +16,7 @@ before_script:
|
||||
script:
|
||||
- python ./tests.py
|
||||
- cd test_project
|
||||
- coverage run --source ../modoboa manage.py test modoboa.core modoboa.lib
|
||||
- coverage run --source ../modoboa manage.py test modoboa.core modoboa.lib modoboa.admin.tests modoboa.limits modoboa.relaydomains
|
||||
|
||||
after_success:
|
||||
- codecov
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#############################
|
||||
Migrating from other software
|
||||
#############################
|
||||
###################
|
||||
Tools for migration
|
||||
###################
|
||||
|
||||
******************************
|
||||
Migrate existing IMAP accounts
|
||||
******************************
|
||||
|
||||
`OfflineIMAP extension <https://github.com/modoboa/modoboa-imap-migration>`_.
|
||||
|
||||
************
|
||||
PostfixAdmin
|
||||
|
||||
@@ -49,6 +49,52 @@ you did choose. See :ref:`webservers` for more details.
|
||||
Specific upgrade instructions
|
||||
*****************************
|
||||
|
||||
1.4.0
|
||||
=====
|
||||
|
||||
.. warning::
|
||||
|
||||
Please make sure to use Modoboa 1.3.5 with an up-to-date database
|
||||
before an upgrade to 1.4.0.
|
||||
|
||||
.. warning::
|
||||
|
||||
Do not follow the regular upgrade procedure for this version.
|
||||
|
||||
Some extension have been moved back into the main repository. The main
|
||||
reason for that is that using Modoboa without them doesn't make sense.
|
||||
|
||||
First of all, you must rename the following applications listed inside
|
||||
the ``MODOBOA_APPS`` variable:
|
||||
|
||||
+--------------------------+--------------------+
|
||||
|Old name |New name |
|
||||
+==========================+====================+
|
||||
|modoboa_admin |modoboa.admin |
|
||||
+--------------------------+--------------------+
|
||||
|modoboa_admin_limits |modoboa.limits |
|
||||
+--------------------------+--------------------+
|
||||
|modoboa_admin_relaydomains|modoboa.relaydomains|
|
||||
+--------------------------+--------------------+
|
||||
|
||||
Then, apply the following steps:
|
||||
|
||||
#. Uninstall old extensions::
|
||||
|
||||
$ pip uninstall modoboa-admin modoboa-admin-limits modoboa-admin-relaydomains
|
||||
|
||||
#. Manually migrate database::
|
||||
|
||||
$ cd <instance_dir>
|
||||
$ python manage.py migrate admin 0001 --fake
|
||||
$ python manage.py migrate limits 0001 --fake
|
||||
$ python manage.py migrate relaydomains 0001 --fake
|
||||
$ python manage.py migrate
|
||||
|
||||
#. Finally, update static files::
|
||||
|
||||
$ python manage.py collectstatic
|
||||
|
||||
1.3.5
|
||||
=====
|
||||
|
||||
|
||||
@@ -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 --extensions all --dbtype <mysql|postgres|sqlite> <directory>
|
||||
$ modoboa-admin.py postfix_maps --dbtype <mysql|postgres|sqlite> <directory>
|
||||
|
||||
``<directory>`` is the directory where the files will be
|
||||
stored. Answer the few questions and you're done.
|
||||
@@ -443,12 +443,20 @@ Use the following configuration in the :file:`/etc/postfix/main.cf` file
|
||||
virtual_alias_domains = <driver>:/etc/postfix/sql-domain-aliases.cf
|
||||
virtual_alias_maps = <driver>:/etc/postfix/sql-aliases.cf
|
||||
|
||||
relay_domains = <driver>:/etc/postfix/sql-relaydomains.cf
|
||||
transport_maps =
|
||||
<driver>:/etc/postfix/sql-spliteddomains-transport.cf
|
||||
<driver>:/etc/postfix/sql-relaydomains-transport.cf
|
||||
|
||||
smtpd_recipient_restrictions =
|
||||
...
|
||||
check_recipient_access <driver>:/etc/postfix/sql-maintain.cf
|
||||
# ...
|
||||
check_recipient_access
|
||||
<driver>:/etc/postfix/sql-maintain.cf
|
||||
<driver>:/etc/postfix/sql-relay-recipient-verification.cf
|
||||
permit_mynetworks
|
||||
reject_unauth_destination
|
||||
reject_unverified_recipient
|
||||
...
|
||||
# ...
|
||||
|
||||
smtpd_sender_login_maps =
|
||||
<driver>:/etc/postfix/sql-sender-login-mailboxes.cf
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
################
|
||||
Per-admin limits
|
||||
################
|
||||
|
||||
`Official documentation <http://modoboa-admin-limits.readthedocs.org>`_.
|
||||
@@ -1,5 +0,0 @@
|
||||
#############################
|
||||
Postfix relay domains support
|
||||
#############################
|
||||
|
||||
`Official documentation <http://modoboa-admin-relaydomains.readthedocs.org>`_.
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = "modoboa.admin.apps.AdminConfig"
|
||||
@@ -0,0 +1,151 @@
|
||||
"""Modoboa admin settings and events."""
|
||||
|
||||
import os
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from ..lib import events
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib.form_utils import YesNoField, SeparatorField
|
||||
from modoboa.lib.sysutils import exec_cmd
|
||||
|
||||
|
||||
ADMIN_EVENTS = [
|
||||
"DomainCreated",
|
||||
"DomainModified",
|
||||
"DomainDeleted",
|
||||
"DomainOwnershipRemoved",
|
||||
"GetTagsForDomain",
|
||||
"ExtraDomainMenuEntries",
|
||||
"ExtraDomainFilters",
|
||||
"ExtraDomainQsetFilters",
|
||||
"ExtraDomainTypes",
|
||||
"ExtraDomainWizardSteps",
|
||||
"GetDomainModifyLink",
|
||||
"CheckDomainName",
|
||||
|
||||
"DomainAliasCreated",
|
||||
"DomainAliasDeleted",
|
||||
|
||||
"MailboxCreated",
|
||||
"MailboxDeleted",
|
||||
"MailboxModified",
|
||||
|
||||
"MailboxAliasCreated",
|
||||
"MailboxAliasDeleted",
|
||||
|
||||
"ExtraDomainForm",
|
||||
"FillDomainInstances",
|
||||
|
||||
"ExtraAccountForm",
|
||||
"CheckExtraAccountForm",
|
||||
"FillAccountInstances",
|
||||
|
||||
"ExtraDomainImportHelp",
|
||||
"ImportObject"
|
||||
]
|
||||
|
||||
|
||||
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']
|
||||
|
||||
|
||||
def load_admin_settings():
|
||||
"""Load admin settings."""
|
||||
from .app_settings import AdminParametersForm
|
||||
|
||||
parameters.register(
|
||||
AdminParametersForm, ugettext_lazy("Administration"))
|
||||
events.declare(ADMIN_EVENTS)
|
||||
from . import callbacks
|
||||
@@ -0,0 +1,14 @@
|
||||
"""AppConfig for admin."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AdminConfig(AppConfig):
|
||||
|
||||
"""App configuration."""
|
||||
|
||||
name = "modoboa.admin"
|
||||
verbose_name = "Modoboa admin console"
|
||||
|
||||
def ready(self):
|
||||
from . import handlers
|
||||
@@ -0,0 +1,252 @@
|
||||
"""Event callbacks for modoboa admin."""
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from modoboa.lib import parameters, events
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
from modoboa.lib.exceptions import PermDeniedException, BadRequest, Conflict
|
||||
|
||||
from .models import (
|
||||
Domain, DomainAlias, Mailbox, Alias
|
||||
)
|
||||
|
||||
|
||||
PERMISSIONS = {
|
||||
"DomainAdmins": [
|
||||
["core", "user", "add_user"],
|
||||
["core", "user", "change_user"],
|
||||
["core", "user", "delete_user"],
|
||||
["admin", "domain", "view_domains"],
|
||||
["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"],
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@events.observe("GetExtraRoles")
|
||||
def extra_roles(user, account):
|
||||
"""Return new roles."""
|
||||
filters = events.raiseQueryEvent(
|
||||
"UserCanSetRole", user, "DomainAdmins", account
|
||||
)
|
||||
if user.has_perm("admin.add_domain") and \
|
||||
(not filters or True in filters):
|
||||
return [("DomainAdmins", _("Domain administrator"))]
|
||||
return []
|
||||
|
||||
|
||||
@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.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")}
|
||||
]
|
||||
conditions = (
|
||||
user.has_perm("core.add_user"),
|
||||
user.has_perm("admin.add_alias")
|
||||
)
|
||||
if any(conditions):
|
||||
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 hasattr(user, "mailbox"):
|
||||
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.quota] \
|
||||
if hasattr(admin, "mailbox") 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.lib.permissions import grant_access_to_object
|
||||
from .lib import check_if_domain_exists
|
||||
|
||||
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 hasattr(request.user, "mailbox"):
|
||||
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 hasattr(account, "mailbox"):
|
||||
return
|
||||
mb = account.mailbox
|
||||
if not byuser.can_access(mb):
|
||||
raise PermDeniedException
|
||||
keep_mb_dir = kwargs.get("keep_mb_dir", True)
|
||||
mb.delete(keepdir=keep_mb_dir)
|
||||
@@ -0,0 +1,110 @@
|
||||
"""
|
||||
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", )
|
||||
|
||||
type = "domain"
|
||||
quota = 10
|
||||
enabled = True
|
||||
|
||||
|
||||
class DomainAliasFactory(PermissionFactory):
|
||||
|
||||
"""Factory to create DomainAlias objects."""
|
||||
|
||||
class Meta:
|
||||
model = models.DomainAlias
|
||||
django_get_or_create = ("name", )
|
||||
|
||||
target = factory.SubFactory(DomainFactory)
|
||||
enabled = True
|
||||
|
||||
|
||||
class MailboxFactory(PermissionFactory):
|
||||
|
||||
"""A factory to create Mailbox instances."""
|
||||
|
||||
class Meta:
|
||||
model = models.Mailbox
|
||||
django_get_or_create = ("address", "domain")
|
||||
|
||||
domain = factory.SubFactory(DomainFactory)
|
||||
user = factory.SubFactory(UserFactory)
|
||||
quota = 10
|
||||
enabled = True
|
||||
|
||||
|
||||
class AliasRecipientFactory(factory.django.DjangoModelFactory):
|
||||
|
||||
class Meta:
|
||||
model = models.AliasRecipient
|
||||
|
||||
|
||||
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)
|
||||
|
||||
al = AliasFactory.create(
|
||||
address='forward@test.com', domain=dom
|
||||
)
|
||||
AliasRecipientFactory.create(
|
||||
address='user@external.com', alias=al)
|
||||
|
||||
al = AliasFactory.create(
|
||||
address='alias@test.com', domain=dom
|
||||
)
|
||||
mb = account.mailbox
|
||||
AliasRecipientFactory.create(
|
||||
address=mb.full_address, alias=al, r_mailbox=mb)
|
||||
|
||||
al = AliasFactory.create(
|
||||
address='postmaster@test.com', domain=dom
|
||||
)
|
||||
for address in ['toto@titi.com', 'test@truc.fr']:
|
||||
AliasRecipientFactory.create(address=address, alias=al)
|
||||
|
||||
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)
|
||||
@@ -0,0 +1,19 @@
|
||||
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'
|
||||
]
|
||||
@@ -0,0 +1,512 @@
|
||||
"""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 passwords.fields import PasswordField
|
||||
|
||||
from modoboa.core.models import User
|
||||
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, WizardStep
|
||||
)
|
||||
from modoboa.lib.permissions import get_account_roles
|
||||
from modoboa.lib.web_utils import render_to_json_response
|
||||
|
||||
from ..models import Domain, Mailbox, Alias
|
||||
|
||||
|
||||
class AccountFormGeneral(forms.ModelForm):
|
||||
|
||||
"""General account form."""
|
||||
|
||||
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 = PasswordField(
|
||||
label=ugettext_lazy("Password"), widget=forms.widgets.PasswordInput
|
||||
)
|
||||
password2 = PasswordField(
|
||||
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",
|
||||
"master_user"
|
||||
)
|
||||
|
||||
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', 'master_user', '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 not user.is_superuser:
|
||||
del self.fields["master_user"]
|
||||
|
||||
if "instance" in kwargs:
|
||||
account = kwargs["instance"]
|
||||
domain_disabled = (
|
||||
hasattr(account, "mailbox") and
|
||||
not account.mailbox.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 hasattr(self.instance, "mailbox"):
|
||||
return False
|
||||
return not self.instance.mailbox.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_master_user(self):
|
||||
"""Check role before allowing this mode."""
|
||||
conditions = (
|
||||
self.cleaned_data["master_user"],
|
||||
self.cleaned_data["role"] != "SuperAdmins"
|
||||
)
|
||||
if all(conditions):
|
||||
raise forms.ValidationError(
|
||||
_("Only super administrators are allowed for this mode")
|
||||
)
|
||||
return self.cleaned_data["master_user"]
|
||||
|
||||
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
|
||||
qset = self.mb.aliasrecipient_set.select_related("alias")
|
||||
for ralias in qset:
|
||||
if ralias.alias.recipients_count >= 2:
|
||||
continue
|
||||
name = "aliases_%d" % cpt
|
||||
self._create_field(forms.EmailField, name, ralias.alias.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())
|
||||
|
||||
qset = self.mb.aliasrecipient_set.select_related("alias").filter(
|
||||
alias__internal=False)
|
||||
for ralias in qset:
|
||||
if ralias.alias.address not in aliases:
|
||||
alias = ralias.alias
|
||||
ralias.delete()
|
||||
if alias.recipients_count >= 2:
|
||||
continue
|
||||
alias.delete()
|
||||
else:
|
||||
aliases.remove(ralias.alias.address)
|
||||
if not aliases:
|
||||
return
|
||||
events.raiseEvent(
|
||||
"CanCreate", user, "mailbox_aliases", len(aliases)
|
||||
)
|
||||
for alias in aliases:
|
||||
if self.mb.aliasrecipient_set.select_related("alias").filter(
|
||||
alias__address=alias).exists():
|
||||
continue
|
||||
local_part, domname = split_mailbox(alias)
|
||||
al = Alias(address=alias, enabled=account.is_active)
|
||||
al.domain = Domain.objects.get(name=domname)
|
||||
al.save()
|
||||
al.set_recipients([self.mb.full_address])
|
||||
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(
|
||||
WizardStep(
|
||||
"general", AccountFormGeneral, _("General"),
|
||||
new_args=[request.user]
|
||||
)
|
||||
)
|
||||
self.add_step(
|
||||
WizardStep(
|
||||
"mail", AccountFormMail, _("Mail"),
|
||||
"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"))
|
||||
@@ -0,0 +1,100 @@
|
||||
"""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.lib.email_utils import split_mailbox
|
||||
from modoboa.lib.form_utils import (
|
||||
DynamicForm
|
||||
)
|
||||
|
||||
from ..models import Domain, Alias
|
||||
from .base import EmailField
|
||||
|
||||
|
||||
class AliasForm(forms.ModelForm, DynamicForm):
|
||||
|
||||
"""A form to create/modify an alias."""
|
||||
|
||||
address = EmailField(
|
||||
label=ugettext_lazy("Email address"),
|
||||
help_text=ugettext_lazy(
|
||||
"The alias address. To create a catchall alias, just enter the "
|
||||
"domain name (@domain.tld)."
|
||||
),
|
||||
widget=forms.TextInput(attrs={"class": "form-control"})
|
||||
)
|
||||
recipients = EmailField(
|
||||
label=ugettext_lazy("Recipients"), required=False,
|
||||
help_text=ugettext_lazy(
|
||||
"Addresses 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 = ("address", "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
|
||||
['address', '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:
|
||||
alias = kwargs["instance"]
|
||||
if not alias.domain.enabled:
|
||||
self.fields["enabled"].widget.attrs["disabled"] = "disabled"
|
||||
cpt = 1
|
||||
for rcpt in alias.aliasrecipient_set.filter(alias__internal=False):
|
||||
name = "recipients_%d" % cpt
|
||||
self._create_field(forms.EmailField, name, rcpt.address, 2)
|
||||
cpt += 1
|
||||
|
||||
def clean_address(self):
|
||||
"""Check if address points to a local domain."""
|
||||
localpart, domname = split_mailbox(self.cleaned_data["address"])
|
||||
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["address"].lower()
|
||||
|
||||
def clean(self):
|
||||
"""Check it there is at least one recipient."""
|
||||
super(AliasForm, self).clean()
|
||||
for field, value in self.cleaned_data.items():
|
||||
if field.startswith("recipients") and value:
|
||||
return self.cleaned_data
|
||||
self.add_error("recipients", _("No recipient defined"))
|
||||
return self.cleaned_data
|
||||
|
||||
def save(self, commit=True):
|
||||
"""Custom save method."""
|
||||
alias = super(AliasForm, self).save(commit=False)
|
||||
local_part, domname = split_mailbox(self.cleaned_data["address"])
|
||||
alias.domain = Domain.objects.get(name=domname)
|
||||
if commit:
|
||||
alias.save()
|
||||
address_list = [
|
||||
value for field, value in self.cleaned_data.items()
|
||||
if field.startswith("recipients") and value
|
||||
]
|
||||
alias.set_recipients(address_list)
|
||||
return alias
|
||||
@@ -0,0 +1,26 @@
|
||||
"""Custom form tools."""
|
||||
|
||||
import re
|
||||
|
||||
from django.core.validators import EmailValidator
|
||||
from django.forms.fields import EmailField as OriginalEmailField
|
||||
|
||||
|
||||
class CustomEmailValidator(EmailValidator):
|
||||
|
||||
"""Allow empty user_part."""
|
||||
|
||||
user_regex = re.compile(
|
||||
r"(^$"
|
||||
r"|^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z" # dot-atom
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)', # quoted-string
|
||||
re.IGNORECASE)
|
||||
|
||||
validate_email = CustomEmailValidator()
|
||||
|
||||
|
||||
class EmailField(OriginalEmailField):
|
||||
|
||||
"""A field that accepts email addresses."""
|
||||
|
||||
default_validators = [validate_email]
|
||||
@@ -0,0 +1,405 @@
|
||||
"""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.lib import events, parameters
|
||||
from modoboa.lib.exceptions import ModoboaException, Conflict
|
||||
from modoboa.lib.form_utils import (
|
||||
DomainNameField, YesNoField, WizardForm, WizardStep, DynamicForm, TabForms
|
||||
)
|
||||
from modoboa.lib.web_utils import render_to_json_response
|
||||
|
||||
from ..lib import check_if_domain_exists
|
||||
from ..models import (
|
||||
Domain, DomainAlias, Mailbox, Alias, Quota
|
||||
)
|
||||
|
||||
DOMAIN_TYPES = [
|
||||
("domain", _("Domain")),
|
||||
]
|
||||
DOMAIN_TYPES += events.raiseQueryEvent("ExtraDomainTypes")
|
||||
|
||||
|
||||
class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
|
||||
"""A form to create/edit a domain."""
|
||||
|
||||
type = forms.ChoiceField(
|
||||
label=ugettext_lazy("Type"), choices=DOMAIN_TYPES
|
||||
)
|
||||
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."
|
||||
)
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Domain
|
||||
fields = ("name", "type", "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...
|
||||
"""
|
||||
cleaned_data = super(DomainFormGeneral, self).clean()
|
||||
if self._errors:
|
||||
return 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)
|
||||
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):
|
||||
|
||||
"""A form containing options for domain creation."""
|
||||
|
||||
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, *args, **kwargs):
|
||||
if not self.fields:
|
||||
return
|
||||
if self.cleaned_data["create_dom_admin"] == "no":
|
||||
return
|
||||
user = kwargs.pop("user")
|
||||
domain = kwargs.pop("domain")
|
||||
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 domain.type == "domain" and \
|
||||
self.cleaned_data["create_aliases"] == "yes":
|
||||
events.raiseEvent("CanCreate", user, "mailbox_aliases")
|
||||
alias = Alias(
|
||||
address="postmaster@{}".format(domain.name),
|
||||
domain=domain, enabled=True
|
||||
)
|
||||
alias.save()
|
||||
alias.set_recipients([mb.full_address])
|
||||
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 = []
|
||||
self.domain = None
|
||||
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:
|
||||
self.domain = kwargs["instances"]["general"]
|
||||
cbargs += [self.domain]
|
||||
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):
|
||||
domadmins = [u for u in self.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": self.domain.name,
|
||||
"action": reverse(
|
||||
"admin:domain_change", args=[self.domain.pk]),
|
||||
"formid": "domform",
|
||||
"domain": self.domain,
|
||||
"domadmins": domadmins
|
||||
})
|
||||
|
||||
def is_valid(self):
|
||||
"""Custom validation.
|
||||
|
||||
We just save the current name before it is potentially
|
||||
modified.
|
||||
|
||||
"""
|
||||
if "general" in self.instances:
|
||||
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.
|
||||
"""
|
||||
if not self.forms:
|
||||
return
|
||||
first_form = self.forms[0]["instance"]
|
||||
options = {}
|
||||
if isinstance(first_form, DomainFormGeneral):
|
||||
options["domalias_post_create"] = True
|
||||
first_form.save(self.request.user, **options)
|
||||
for f in self.forms[1:]:
|
||||
f["instance"].save(self.request.user)
|
||||
|
||||
def done(self):
|
||||
if "general" in self.instances:
|
||||
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(
|
||||
WizardStep(
|
||||
"general", DomainFormGeneral, _("General"),
|
||||
"admin/domain_general_form.html"
|
||||
)
|
||||
)
|
||||
steps = events.raiseQueryEvent("ExtraDomainWizardSteps")
|
||||
for step in steps:
|
||||
self.add_step(step)
|
||||
self.add_step(
|
||||
WizardStep(
|
||||
"options", DomainFormOptions, _("Options"),
|
||||
"admin/domain_options_form.html",
|
||||
[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)
|
||||
for step in self.steps[1:]:
|
||||
if not step.check_access(self):
|
||||
continue
|
||||
try:
|
||||
step.form.save(user=self.request.user, domain=domain)
|
||||
except ModoboaException:
|
||||
from django.db import transaction
|
||||
transaction.rollback()
|
||||
raise
|
||||
return render_to_json_response(_("Domain created"))
|
||||
@@ -0,0 +1,45 @@
|
||||
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"
|
||||
@@ -0,0 +1,46 @@
|
||||
"""Forms related to forwards management."""
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
from modoboa.lib.exceptions import BadRequest, PermDeniedException
|
||||
|
||||
from ..models import Domain
|
||||
|
||||
|
||||
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 get_recipients(self):
|
||||
recipients = []
|
||||
rawdata = self.cleaned_data["dest"].strip()
|
||||
if not rawdata:
|
||||
return
|
||||
for rcpt in rawdata.split(","):
|
||||
local_part, domname = split_mailbox(rcpt)
|
||||
if not local_part or not domname:
|
||||
raise BadRequest("Invalid mailbox syntax for %s" % rcpt)
|
||||
try:
|
||||
Domain.objects.get(name=domname)
|
||||
except Domain.DoesNotExist:
|
||||
recipients += [rcpt]
|
||||
else:
|
||||
raise PermDeniedException(
|
||||
_("You can't define a forward to a local destination. "
|
||||
"Please ask your administrator to create an alias "
|
||||
"instead.")
|
||||
)
|
||||
return recipients
|
||||
@@ -0,0 +1,43 @@
|
||||
"""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"
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,76 @@
|
||||
"""Django signal handlers for admin."""
|
||||
|
||||
from django.db.models import signals
|
||||
from django.dispatch import receiver
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
@receiver(signals.post_save, sender=models.DomainAlias)
|
||||
def create_alias_for_domainalias(sender, instance, **kwargs):
|
||||
"""Create a dedicated alias for domain alias."""
|
||||
if not kwargs.get("created"):
|
||||
return
|
||||
alias = models.Alias.objects.create(
|
||||
address="@{}".format(instance.name), enabled=True, internal=True)
|
||||
models.AliasRecipient.objects.create(
|
||||
address="@{}".format(instance.target.name), alias=alias)
|
||||
|
||||
|
||||
@receiver(signals.post_delete, sender=models.DomainAlias)
|
||||
def remove_alias_for_domainalias(sender, instance, **kwargs):
|
||||
"""Remove the alias associated to domain alias."""
|
||||
models.Alias.objects.filter(
|
||||
address="@{}".format(instance.name)).delete()
|
||||
|
||||
|
||||
@receiver(signals.post_save, sender=models.Mailbox)
|
||||
def manage_alias_for_mailbox(sender, instance, **kwargs):
|
||||
"""Create or update a "self alias" for mailbox (catchall)."""
|
||||
if kwargs.get("created"):
|
||||
alias, created = models.Alias.objects.get_or_create(
|
||||
address=instance.full_address, domain=instance.domain,
|
||||
internal=True)
|
||||
models.AliasRecipient.objects.create(
|
||||
address=instance.full_address, alias=alias, r_mailbox=instance)
|
||||
return
|
||||
old_address = getattr(instance, "old_full_address", None)
|
||||
if old_address is None or old_address == instance.full_address:
|
||||
return
|
||||
alr = models.AliasRecipient.objects.select_related("alias").get(
|
||||
alias__address=old_address, address=old_address,
|
||||
r_mailbox=instance, alias__internal=True)
|
||||
alr.address = instance.full_address
|
||||
alr.save()
|
||||
alr.alias.address = instance.full_address
|
||||
alr.alias.save()
|
||||
|
||||
|
||||
@receiver(signals.pre_delete, sender=models.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 import events
|
||||
from modoboa.lib.permissions import ungrant_access_to_object
|
||||
|
||||
mb = kwargs['instance']
|
||||
events.raiseEvent("MailboxDeleted", mb)
|
||||
ungrant_access_to_object(mb)
|
||||
for ralias in mb.aliasrecipient_set.select_related("alias"):
|
||||
alias = ralias.alias
|
||||
ralias.delete()
|
||||
if not alias.aliasrecipient_set.exists():
|
||||
alias.delete()
|
||||
|
||||
|
||||
@receiver(signals.post_delete, sender=models.Mailbox)
|
||||
def remove_alias_for_mailbox(sender, instance, **kwargs):
|
||||
"""Remove "self alias" for this mailbox."""
|
||||
models.Alias.objects.filter(
|
||||
address=instance.full_address).delete()
|
||||
@@ -0,0 +1,155 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""Internal library for admin."""
|
||||
|
||||
from functools import wraps
|
||||
from itertools import chain
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Q
|
||||
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 .models import Domain, DomainAlias, 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 hasattr(request.user, "mailbox"):
|
||||
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:
|
||||
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 = Domain.objects.get_for_admin(user)
|
||||
if domfilter:
|
||||
domains = domains.filter(type=domfilter)
|
||||
if searchquery is not None:
|
||||
q = Q(name__contains=searchquery)
|
||||
q |= Q(domainalias__name__contains=searchquery)
|
||||
domains = domains.filter(q).distinct()
|
||||
qset_filters = events.raiseDictEvent(
|
||||
"ExtraDomainQsetFilters", domfilter, extrafilters
|
||||
)
|
||||
if qset_filters:
|
||||
domains = domains.filter(**qset_filters)
|
||||
return domains
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
def import_domain(user, row, formopts):
|
||||
"""Specific code for domains import"""
|
||||
if not user.has_perm("admin.add_domain"):
|
||||
raise PermDeniedException(_("You are not allowed to import domains"))
|
||||
dom = Domain()
|
||||
dom.from_csv(user, row)
|
||||
|
||||
|
||||
def import_domainalias(user, row, formopts):
|
||||
"""Specific code for domain aliases import"""
|
||||
if not user.has_perm("admin.add_domainalias"):
|
||||
raise PermDeniedException(
|
||||
_("You are not allowed to import domain aliases."))
|
||||
domalias = DomainAlias()
|
||||
domalias.from_csv(user, row)
|
||||
|
||||
|
||||
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)
|
||||
@@ -0,0 +1,890 @@
|
||||
# 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 <miris@kunago.com>, 2013-2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2015-01-06 10:05+0000\n"
|
||||
"Last-Translator: Miroslav Abrahám <miris@kunago.com>\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"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Schránky"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Spravovat schránky v souborovém systému"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Majitel schránky"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
msgid "The UNIX account who owns mailboxes on the filesystem"
|
||||
msgstr "Účet UNIXu, který vlastní schránky v souborovém systému"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr "Výchozí kvóta domény"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
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á."
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Automatické odstranění účtu"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Automatické vytvoření domény/schránky"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr "Musí se jednat o kladné číslo"
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr "Správa"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
#, fuzzy
|
||||
#| msgid "Create a domain administrator"
|
||||
msgid "Domain administrator"
|
||||
msgstr "Vytvořit správce domény"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Domény"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Identity"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Přeposlat"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Import účtu nebyl úspěšný (%s): doména neexistuje"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "Schránka %s již existuje"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Import účtu selhal (%s): chybná hodnota kvóty"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr "doménový alias"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Uživatelské jméno"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
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."
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Role"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Vybrat"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Jaká úroveň oprávnění bude tomuto uživateli nastavena"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Heslo"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Potvrzení"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Vložte stejné heslo jako v poli výše, pro jeho ověření."
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Povoleno"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Obě pole s heslem se neshodují."
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "Nemůžete zakázat váš vlastní účet"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Kvóta"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias(y)"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "Doména neexistuje"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Doména(y)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Doména(y) pod správou uživatele"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Obecné"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Mail"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Oprávnění"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Účet aktualizován"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Nový účet"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Účet vytvořen"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "Emailová adresa"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The alias address (without the domain part). For a 'catch-all' address, "
|
||||
#| "just enter an * character."
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"Alias adresy (bez části označující doménu). Pro vytvoření doménového koše "
|
||||
"vložte znak '*'."
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Příjemci"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Mailbox(es) this alias will point to. Indicate only one address per "
|
||||
#| "input, press ENTER to add a new input."
|
||||
msgid ""
|
||||
"Addresses 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."
|
||||
|
||||
#: 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ě"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Nebyl určen příjemce"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr "Doména"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr "Typ"
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "%s s tímto názvem již existuje"
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr "doména"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Vytvořit správce domény"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Automaticky vytvořit správce této domény"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Jméno"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Vytvořit aliasy"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Automaticky vytvořit běžné aliasy pro tuto doménu"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Neplatný formát"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "Uživatel '%s' již existuje"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Doména upravena"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Možnosti"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Nová doména"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Doména vytvořena"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Název souboru"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Oddělovač"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Příjemce(i)"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Uveďte jednoho nebo více příjemců oddělených pomocí ','"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Ponechat místní kopie"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
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"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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."
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Vybrat soubor"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Při výskytu chyby pokračovat"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Nepovažovat duplikáty objektů za chybu"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Zašifrovat hesla"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr "Schránka je vyžadována"
|
||||
|
||||
#: admin/lib.py:120
|
||||
#, fuzzy
|
||||
#| msgid "You can't delete your own domain"
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "Nemůžete smazat vlastní doménu"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "adresa"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
#, fuzzy
|
||||
#| msgid "The alias name"
|
||||
msgid "The alias address."
|
||||
msgstr "Název aliasu"
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "povoleno"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Zatrhněte pole pro povolení tohoto aliasu"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "distribuční seznam"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "přeposlat"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
#, fuzzy
|
||||
#| msgid "Invalid request"
|
||||
msgid "Invalid address"
|
||||
msgstr "Neplatný požadavek"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
#, fuzzy
|
||||
#| msgid "Local recipient %s not found"
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Místní příjemce %s nebyl nalezen"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Neplatný řádek: %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "Doména '%s' neexistuje"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "název"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "Doménové jméno"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Zatrhněte pole pro povolení této domény"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Neplatný řádek"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr "Neplatná hodnota kvóty u domény '%s'"
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "Název aliasu"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "cíl"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "Doména, na kterou tento alias odkazuje"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Neznámá doména %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Adresa schránky (bez části @doména.tld)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Nebylo možné zjistit umístění schránky (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, 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)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "Kvóta je vyžadována"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr "Doména je zakázána"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiky"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr "Domény a identity"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr "Globální počitadla"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr "Počet"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Doménové aliasy"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr "Počitadla dle domén"
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Značky"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Akce"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr "zákázáno"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Správci"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Různé"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr " Nebyl určen správce domény"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Datum vytvoření"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Datum poslední změny"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Aliasy schránek"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Automaticky přesměrovat emaily na jinou adresu"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Aktualizovat"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Celé jméno/Příjemce"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Nápověda"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Importuji..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Zvolte hodnotu"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Použít výchozí hodnotu domény"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Adresa"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Hodnota"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Omezení"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Využití (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Hledat"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "Aktivovaný"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "Aktivovaná"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr "Seznam domén"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Přidat doménu"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Import"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Export"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Seznam identit"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Seznam kvót"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Přidat účet"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Přidat alias"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Přidat přeposílání"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Přidat distribuční seznam"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Zobrazit seznam identit domény"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "Smazat %s?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Odstranit toto oprávnění"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Alias s tímto názvem již existuje"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Vytvořit"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Nový distribuční seznam"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Distribuční seznam vytvořen"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Nový alias"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias vytvořen"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Nové přeposílání"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Přeposílání vytvořeno"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Distribuční seznam upraven"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Přeposílání upraveno"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Alias upraven"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "Nemůžete smazat vlastní doménu"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
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"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Exportovat identity"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Exportovat domény"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Neplatný požadavek"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Účet smazán"
|
||||
msgstr[1] "Účty smazány"
|
||||
msgstr[2] "Účtů smazáno"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "Objekt již existuje: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d objektů úspěšně importováno"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Nahrajte CSV soubor, který bude mít jednotlivé řádky v některém z uvedených "
|
||||
"formátů:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>domain; název; kvóta, povoleno</em></li>\n"
|
||||
"<li><em>domainalias; název; cílová doména; povoleno</em></li>\n"
|
||||
"%s\n"
|
||||
"</ul>\n"
|
||||
"<p>První element každého řádku je povinný a musí být shodný s některou z "
|
||||
"předchozích hodnot.</p>\n"
|
||||
"<p>Můžete také použít jiný oddělovač hodnot.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Importovat domény"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Nahrajte CSV soubor, který bude mít jednotlivé řádky v některém z uvedených "
|
||||
"formátů:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; přihlašovací jméno; heslo; křestní jméno; příjmení; "
|
||||
"povoleno; skupina; adresa; kvóta; [, doména, ...]</em></li>\n"
|
||||
"<li><em>alias; adresa; povoleno; interní příjemce</em></li>\n"
|
||||
"<li><em>forward; adresa; povoleno; externí příjemce</em></li>\n"
|
||||
"<li><em>dlist; adresa; povoleno; příjemce; příjemce; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>První element každého řádku je povinný a musí být shodný s některou z "
|
||||
"předchozích hodnot.</p>\n"
|
||||
"<p>Můžete také použít jiný oddělovač hodnot.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Importovat identity"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Přeposílání aktualizováno"
|
||||
@@ -0,0 +1,55 @@
|
||||
# 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 <miris@kunago.com>, 2013,2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2015-01-06 10:05+0000\n"
|
||||
"Last-Translator: Miroslav Abrahám <miris@kunago.com>\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"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr "Žádná další doména k zobrazení"
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Nemazat adresář domény"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Tento krok odstraní VŠECHNA data související s touto doménou."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
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ů."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Není určen správce domény"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr "Žádná další identita k zobrazení"
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Nemazat adresář schránky"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr "Žádná další kvóta k zobrazení"
|
||||
@@ -0,0 +1,876 @@
|
||||
# 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 <arvedui@posteo.de>, 2014
|
||||
# controlc.de, 2015
|
||||
# Patrick Koetter <p@state-of-mind.de>, 2010
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2015-09-09 09:33+0000\n"
|
||||
"Last-Translator: controlc.de\n"
|
||||
"Language-Team: German (http://www.transifex.com/tonio/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"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Postfächer"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Postfächer im Dateisystem verwalten"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
msgid ""
|
||||
"Rename or remove mailboxes on the filesystem when they get renamed or "
|
||||
"removed within Modoboa"
|
||||
msgstr ""
|
||||
"Postfächer auch in Dateisystem umbenennen oder entfernen wenn sie in Modoboa "
|
||||
"umbenannt oder entfernt werden"
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Postfach-Besitzer"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr "Standard-Domainquota"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
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“"
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Automatische Konto-Entfernung"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
msgid "When a mailbox is removed, also remove the associated account"
|
||||
msgstr "Beim Löschen des Postfachs auch das Konto entfernen."
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Automatische Domain- /Postfach-Erstellung"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
msgid "Create a domain and a mailbox when an account is automatically created."
|
||||
msgstr ""
|
||||
"Erstelle eine Domain und ein Postfach, wenn ein Konto automatisch erstellt "
|
||||
"wurde."
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr "Muss eine positive Ganzzahl sein"
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr "Verwaltung"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
msgid "Domain administrator"
|
||||
msgstr "Domain Administrator"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Domains"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Identitäten"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Weiterleiten"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Kann Konto nicht importieren (%s): Die Domain existiert nicht"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "Postfach %s existiert bereits"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Konto Import fehlgeschlagen (%s): ungültiger Quota-Wert"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr "Domain-Alias"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Benutzername"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
msgid ""
|
||||
"The user's name. Must be a valid e-mail address for simple users or "
|
||||
"administrators with a mailbox."
|
||||
msgstr ""
|
||||
"Der Benutzername. Muss eine gültige E-Mail-Adresse für 'Normale Benutzer' "
|
||||
"oder Administratoren mit einer Mailbox sein."
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Rolle"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Auswählen"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Rechte, die der Benutzer haben wird"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Passwort"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Bestätigung"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Passwort bestätigen"
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Aktiviert"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr "Nur Super-Administratoren dürfen diesen Modus benutzen."
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Die angegebenen Passwörter stimmen nicht überein"
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "Sie können Ihr eigenes Konto nicht deaktivieren"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Quota"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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 dieses Postfach. Geben Sie einen individuellen Wert an oder "
|
||||
"nutzen Sie den Standardwert der Domain. Lassen Sie das Feld leer für "
|
||||
"unbegrenztes Quota (Domain-Administratoren ist dies nicht gestattet)."
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias(e)"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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 dieses Postfach. Geben Sie jeweils nur eine Adresse pro Eingabe "
|
||||
"an. Bestätigen Sie die Eingabe mit ENTER. Geben Sie '*' an, um einen "
|
||||
"'catchall'-Alias (Bsp: *@example.com) zu erstellen."
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "Domain existiert nicht"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Domain(s)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Domain(s), die dieser Benutzer administriert"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Allgemein"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Berechtigungen"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Konto aktualisiert"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Neues Konto"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Konto erstellt"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "E-Mail Adresse"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"Die Alias-Adresse. Geben Sie nur den Domainnamen (@domain.tld) für eine "
|
||||
"'catch-all' Alias an."
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Empfänger"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
msgid ""
|
||||
"Addresses this alias will point to. Indicate only one address per input, "
|
||||
"press ENTER to add a new input."
|
||||
msgstr ""
|
||||
"Adressen, auf die der Alias verweist. Geben Sie jeweils nur eine Adresse ein "
|
||||
"und bestätigen Sie mit ENTER."
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "Der Zugriff auf diese Domain ist Ihnen nicht gestattet"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Keine Empfänger angegeben"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr "Domain"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr "Typ"
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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 Domain. Geben Sie jeweils nur eine Adresse pro "
|
||||
"Eingabefeld an. Bestätigen Sie mit ENTER, um ein neues Eingabefeld zu "
|
||||
"erhalten."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "Ein %s mit diesem Namen existiert bereits"
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr "Domain"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Domain-Administrator erstellen"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Automatisch Administrator für diese Domain anlegen"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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 angehängt."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Aliase erstellen"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Automatisch Standard-Aliase für Domain anlegen"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Ungültiges Format"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "Benutzer %s existiert bereits"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Domain verändert"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Optionen"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Neue Domain"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Domain erstellt."
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Dateiname"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Separator"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Empfänger"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Geben sie einen oder mehrere, durch ',' separierte Empfänger an"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Lokale Kopien behalten"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr "Nachricht weiterleiten und Kopie in Mailbox ablegen"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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."
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Wählen Sie eine Datei"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Bei Fehler fortfahren"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Doppelte Objekte nicht als Fehler behandeln"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Passwörter verschlüsseln"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr "Ein Postfach ist erforderlich"
|
||||
|
||||
#: admin/lib.py:120
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "Sie verfügen nicht über ausreichend Rechte, um Domains zu importieren."
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr ""
|
||||
"Sie verfügen nicht über ausreichend Rechte, um Domain Aliase zu importieren."
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "Adresse"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
msgid "The alias address."
|
||||
msgstr "Die Alias-Adresse"
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "aktiviert"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Auswählen, um den Alias zu aktivieren"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "Verteilerliste"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "Weiterleitung"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "Alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
msgid "Invalid address"
|
||||
msgstr "Ungültige Adresse"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Lokaler Empfänger {}@{} nicht gefunden"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Ungültige Zeile: %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "Domain '%s' existiert nicht"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "Name"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "Name der Domain"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Auswählen, um diese Domain zu aktivieren"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Ungültige Zeile"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr "Ungültiger Quota-Wert für Domain '%s'"
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "Der Alias-Name"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "Ziel"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "Domain, auf die dieser Alias verweist"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Unbekannte Domain %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Postfach-Adresse (ohne den '@domain.tld' Teil)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Der Speicherort des Postfachs (%s) konnte nicht bestimmt werden"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, 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)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "Ein Quota ist erforderlich"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr "Domain ist deaktiviert"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
#: admin/templates/admin/domain_options_form.html:7
|
||||
msgid "You can't create a new domain administrator"
|
||||
msgstr "Sie können keinen neuen Domain-Administrator erstellen"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiken"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr "Domains und Identitäten"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr "Zentrale Zähler"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr "Anzahl"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Domain-Aliase"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr "pro Domain"
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Aktionen"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr "deaktiviert"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Administratoren"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Verschiedenes"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Kein Domain-Administrator definiert"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Erstellungsdatum"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Datum der letzten Änderung"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Postfach-Aliase"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Nachrichten automatisch an andere Adresse weiterleiten"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Aktualisieren"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Name/Empfänger"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Hilfe"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Importiere…"
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Wert auswählen"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Standardwert der Domain verwenden"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Adresse"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Wert"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Limit"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Verwendung (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Suchen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "aktiviert_m"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "aktiviert_f"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr "Domain-Liste"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Domain hinzufügen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Import"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Export"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Identitäten-Liste"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Quota-Liste"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Konto hinzufügen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Alias hinzufügen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Weiterleitung hinzufügen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Verteilerliste hinzufügen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Domain-Identitäten anzeigen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "%s löschen?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Diese Berechtigung entfernen"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Ein Alias mit diesem Namen existiert bereits"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Erstellen"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Neue Verteilerliste"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Verteilerliste erstellt"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Neuer Alias"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias erstellt"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Neue Weiterleitung"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Weiterleitung erstellt"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Verteilerliste verändert"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Weiterleitung verändert"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Alias verändert"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "Sie können Ihre eigene Domain nicht löschen"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Domain gelöscht"
|
||||
msgstr[1] "Domains gelöscht"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Identitäten exportieren"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Domains exportieren"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Ungültige Anfrage"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Konto gelöscht"
|
||||
msgstr[1] "Konten gelöscht"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "Objekt existiert bereits: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d Objekte erfolgreich importiert"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Verwenden sie eine CSV-Datei mit einem der folgenden Formate:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>Das erste Element jeder Zeile ist zwingend und muss gleich zum "
|
||||
"vorhergehenden sein.</p>\n"
|
||||
"<p>Ein anderes Zeichen als Trenner ist gestattet.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Domains importieren"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Verwenden sie eine CSV-Datei in einem der folgenden Formate:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>Das erste Element einer Zeile ist zwingend und muss gleich mit einem der "
|
||||
"vorhergehenden sein.</p>\n"
|
||||
"\n"
|
||||
"<p>Ein anderes Zeichen als Separator ist gestattet.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Identitäten importieren"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Weiterleitung aktualisiert"
|
||||
@@ -0,0 +1,57 @@
|
||||
# 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 <arvedui@posteo.de>, 2014
|
||||
# Patrick Koetter <p@state-of-mind.de>, 2010
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2014-12-01 12:12+0000\n"
|
||||
"Last-Translator: Arvedui <arvedui@posteo.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"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr "Keine weiteren Domains"
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Verzeichnis der Domain nicht löschen"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Diese Aktion wird ALLE mit der Domain verbundenen Daten löschen."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
"Diese Aktion wird ALLE mit der Domain verbundenen Daten, außer Mailkonten, "
|
||||
"löschen."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Domain-Administrator fehlt"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr "Keine weiteren Identitäten"
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Verzeichnis der Mailbox nicht löschen"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr "Keine weiteren Quotas"
|
||||
@@ -0,0 +1,822 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
msgid ""
|
||||
"Rename or remove mailboxes on the filesystem when they get renamed or "
|
||||
"removed within Modoboa"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
msgid "The UNIX account who owns mailboxes on the filesystem"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
msgid ""
|
||||
"Default quota (in MB) applied to freshly created domains with no value "
|
||||
"specified. A value of 0 means no quota."
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
msgid "When a mailbox is removed, also remove the associated account"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
msgid "Create a domain and a mailbox when an account is automatically created."
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
msgid "Domain administrator"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
msgid ""
|
||||
"The user's name. Must be a valid e-mail address for simple users or "
|
||||
"administrators with a mailbox."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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 ""
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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 ""
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
msgid ""
|
||||
"Addresses this alias will point to. Indicate only one address per input, "
|
||||
"press ENTER to add a new input."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
msgid ""
|
||||
"Default quota in MB applied to mailboxes. Leave empty to use the default "
|
||||
"value."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
msgid ""
|
||||
"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
|
||||
"add a new input."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
msgid ""
|
||||
"The administrator's name. Don't include the domain's name here, it will be "
|
||||
"automatically appended."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
msgid ""
|
||||
"You can't define a forward to a local destination. Please ask your "
|
||||
"administrator to create an alias instead."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
msgid "Check this option if passwords contained in your file are not crypted"
|
||||
msgstr ""
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr ""
|
||||
|
||||
#: admin/lib.py:120
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr ""
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
msgid "The alias address."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
msgid "Invalid address"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, python-format
|
||||
msgid "Quota is greater than the allowed domain's limit (%dM)"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_options_form.html:7
|
||||
msgid "You can't create a new domain administrator"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,52 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,899 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Pedro Gracia <lasarux@neuroomante.com>, 2011-2013
|
||||
# Pedro Gracia <pedro.gracia@impulzia.com>, 2010-2011
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2013-10-01 09:56+0000\n"
|
||||
"Last-Translator: Pedro Gracia <lasarux@neuroomante.com>\n"
|
||||
"Language-Team: Spanish (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"es/)\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Mailboxes"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Manejar mailboxes en el sistema de fichero"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
#, 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"
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Propietario de los mailboxes"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
msgid "The UNIX account who owns mailboxes on the filesystem"
|
||||
msgstr "Cuenta de UNIX que posee los mailboxes en el sistema de ficheros"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
#, fuzzy
|
||||
msgid "Default domain quota"
|
||||
msgstr "Límites por defecto"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
msgid ""
|
||||
"Default quota (in MB) applied to freshly created domains with no value "
|
||||
"specified. A value of 0 means no quota."
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Elminar cuentas automáticamente"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
msgid "When a mailbox is removed, also remove the associated account"
|
||||
msgstr "Cuando un mailbox es eliminado, también lo es su cuenta asociada."
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
#, fuzzy
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Dominio creado"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
msgid "Create a domain and a mailbox when an account is automatically created."
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
#, fuzzy
|
||||
msgid "Administration"
|
||||
msgstr "Administradores"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
#, fuzzy
|
||||
#| msgid "Create a domain administrator"
|
||||
msgid "Domain administrator"
|
||||
msgstr "Crear un administrador del dominio"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Dominios"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Identidades"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Siguiente"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Falló la importación de la cuenta (%s): el dominio no existe"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "El mailbox %s ya existe"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, fuzzy, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Falló la importación de la cuenta (%s): el dominio no existe"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
#, fuzzy
|
||||
msgid "domain alias"
|
||||
msgstr "Alias del dominio"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Nombre de usuario"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
#, 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"
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Rol"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Elija"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Qué nivel de permiso tendrá este usuario"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Contraseña"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Confirmación"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Introduzca la misma contraseña que arriba, para verificación."
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Activado"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Las contraseñas no concuerdan"
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "No puede deshabilitar su propia cuenta"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "Email"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Cuota"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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)"
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)"
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "El dominio no existe"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Dominio(s)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Dominio(s) que el usuario administra"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "General"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Correo"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Permisos"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Cuenta actualizada"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Nueva cuenta"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Cuenta creada"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "Dirección de email"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The alias address (without the domain part). For a 'catch-all' address, "
|
||||
#| "just enter an * character."
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"La dirección del alias (sin la parte del dominio). Para una dirección que lo "
|
||||
"recoja todo, ponga un asterisco (*)."
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Destinatarios"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Mailbox(es) this alias will point to. Indicate only one address per "
|
||||
#| "input, press ENTER to add a new input."
|
||||
msgid ""
|
||||
"Addresses 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."
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "No tienes acceso a este dominio"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "No ha puesto destinatario"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
#, fuzzy
|
||||
msgid "Domain"
|
||||
msgstr "Dominios"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
#, 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"
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, fuzzy, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "Ya existe un alias con este nombre"
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
#, fuzzy
|
||||
msgid "domain"
|
||||
msgstr "Dominios"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Crear un administrador del dominio"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Automáticamente crear una administrador para este dominio"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Crear alias"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Automáticamente crear alias estándar para este dominio"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Formato inválido"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "El usuario '%s' ya existe"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Dominio modificado"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Opciones"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Nuevo dominio"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Dominio creado"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Nombre del fichero"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Separador"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Destinatario(s)"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Indique uno o más destinatarios separados por una ','"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Mantener copias locales"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr "Reenvía mensajes y guarda copias en su mailbox local"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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."
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Seleccione un fichero"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Continúe en error."
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "No tratar objetos duplicados como error"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Contraseñas cifradas"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
#, fuzzy
|
||||
msgid "A mailbox is required"
|
||||
msgstr "Una cuota es obligatoria"
|
||||
|
||||
#: admin/lib.py:120
|
||||
#, fuzzy
|
||||
#| msgid "You can't delete your own domain"
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "No puedo eliminar su propio dominio"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "dirección"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
#, fuzzy
|
||||
#| msgid "The alias name"
|
||||
msgid "The alias address."
|
||||
msgstr "Nombre del alias"
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "activado"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Marcar para activar este alias"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "Lista de distribución"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "reenvío"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
#, fuzzy
|
||||
#| msgid "Invalid request"
|
||||
msgid "Invalid address"
|
||||
msgstr "Petición inválida"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
#, fuzzy
|
||||
#| msgid "Local recipient %s not found"
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Destinatario local %s no encontrado"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Línea inválida: %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "El dominio '%s' no existe"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "nombre"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "Nombre del dominio"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Marcar para activar este dominio"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Línea inválida"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "Nombre del alias"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "objetivo"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "El dominio al que este alias apunta"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Dominio desconocido %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Dirección del mailbox (sin la parte @dominio.tld)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Fallo al recuperar la localización del mailbox (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, 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)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "Una cuota es obligatoria"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
#, fuzzy
|
||||
msgid "Domain is disabled"
|
||||
msgstr "Dominio eliminado"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
#: admin/templates/admin/domain_options_form.html:7
|
||||
#, fuzzy
|
||||
msgid "You can't create a new domain administrator"
|
||||
msgstr "Crear un administrador del dominio"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Estadísticas"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#, fuzzy
|
||||
msgid "Domains and identities"
|
||||
msgstr "Listar identidades"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
#, fuzzy
|
||||
msgid "Quantity"
|
||||
msgstr "Cuarentena"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Alias del dominio"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Acciones"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
#, fuzzy
|
||||
msgid "disabled"
|
||||
msgstr "activado"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Administradores"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Otros"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "No hay un dominio de administrador definido "
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Fecha de creación"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Última fecha de modificación"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Alias del mailbox"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Reenvía automáticamente los correos a otra dirección"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Actualizar"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Nombre completo/Destinatario"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Ayuda"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Importando..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Elija un valor"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Usar el valor por defecto del dominio"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Dirección"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Límite"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Uso (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Buscar"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "Activado"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "Activado"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
#, fuzzy
|
||||
msgid "List domains"
|
||||
msgstr "Editar el dominio"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Añadir dominio"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Exportar"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Listar identidades"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Listar cuotas"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Añadir cuenta"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Añadir alias"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Añadir reenvío"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Añadir lista de distribución"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Ver las identidades del dominio"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "¿Eliminar %s?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Eliminar este permiso"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Ya existe un alias con este nombre"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Crear"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Nueva lista de distribución"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Lista de distribución creada"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Nuevo alias"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias creado"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Nuevo reenvío"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Reenvío creado"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Lista de distribución modificada"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Reenvío modificado"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Alias modificado"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "No puedo eliminar su propio dominio"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Dominio eliminado"
|
||||
msgstr[1] "Dominios eliminados"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Exportar identidades"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Exportar dominios"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Petición inválida"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Cuenta eliminada"
|
||||
msgstr[1] "Cuentas eliminadas"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "El objeto ya existe: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d objetos importados con éxito"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, fuzzy, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Provea un fichero CSV dónde las líneas respetan uno de los siguientes "
|
||||
"formatos:⏎ <ul>⏎ <li><em>dominio; nombre; cuota; activado</em></li>⏎ "
|
||||
"<li><em>aliasdeldominio; nombre; dominio objetivo; activado</em></li>⏎ </"
|
||||
"ul>⏎ <p>El primer elemento de cada línea es obligatorio y debe ser igual a "
|
||||
"uno de los valores anteriores.</p>⏎ <p>Puede usar un carácter diferente como "
|
||||
"separador.</p>⏎\n"
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Importar dominios"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Importe un fichero CSV dónde las líneas respetan uno de los siguientes "
|
||||
"formatos:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address[, domain, ...]</em></li>⏎\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>⏎\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>⏎\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>⏎\n"
|
||||
"</ul>⏎\n"
|
||||
"<p>El primer elemento de cada línea es obligatorio y debe ser igual al de "
|
||||
"los valores previos.</p>\n"
|
||||
"\n"
|
||||
"<p>Puede usar un carácter diferente como separador.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Importar identidades"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Reenvío actualizado"
|
||||
@@ -0,0 +1,57 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Pedro Gracia <lasarux@neuroomante.com>, 2011,2013
|
||||
# Pedro Gracia <pedro.gracia@impulzia.com>, 2010, 2011
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2013-06-03 16:32+0000\n"
|
||||
"Last-Translator: Pedro Gracia <lasarux@neuroomante.com>\n"
|
||||
"Language-Team: Spanish (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"es/)\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "No eleminar el directorio del dominio"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Esta operación eliminará TODOS los datos asociados a este dominio."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
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."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "No hay un administrador de dominio definido"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "No eliminar el directorio del mailbox"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,874 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2015-09-09 08:33+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: French (http://www.transifex.com/tonio/modoboa/language/fr/)\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Boites"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Gérer les boites sur le système de fichiers"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Propriétaire des boites"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr "Quota de domaine par défaut"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
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é."
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Suppression automatique de compte"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Création automatique de domaine/boite aux lettres"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr "Doit être un entier positif"
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr "Administration"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
msgid "Domain administrator"
|
||||
msgstr "Administrateur de domaine"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Domaines"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Identités"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Transfert"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "L'import du compte a échoué (%s): le domaine n'existe pas"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "La boite %s existe déjà"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "L'import du compte a échoué (%s): mauvais quota"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr "alias de domaine"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Nom d'utilisateur"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
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."
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Rôle"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Choisir"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Quel niveau de permission cet utilisateur aura"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Confirmation"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Entrer le même mot de passe, pour vérification."
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Activé"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr "Seuls les super administrateurs sont autorisés pour ce mode"
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Les deux mots de passe ne correspondent pas."
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "Vous ne pouvez pas désactiver votre propre compte"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Quota"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "Domaine inexistant"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Domaine(s)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Domaine(s) que cet utilisateur administre"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Général"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Courrier"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Permissions"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Compte mis à jour"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Nouveau compte"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Compte créé"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "Adresse email"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"L'adresse de l'alias. Pour créer un alias \"fourre-tout\", saisissez "
|
||||
"uniquement le nom du domaine (@domain.tld)."
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Destinataires"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
msgid ""
|
||||
"Addresses this alias will point to. Indicate only one address per input, "
|
||||
"press ENTER to add a new input."
|
||||
msgstr ""
|
||||
"Les adresses vers lesquelles cet alias pointera. Indiquer une adresse par "
|
||||
"champ, appuyer sur ENTREE pour ajouter un nouveau champ."
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "Vous n'avez pas accès à ce domaine"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Aucune destinataire défini"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr "Domaine"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "Un %s de ce nom existe déjà"
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr "domaine"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Créer un administrateur de domaine"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Créer automatiquement un administrateur pour ce domaine"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Créer des alias"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Créer automatiquement des alias standard pour ce domaine"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Format invalide"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "L'utilisateur '%s' existe déjà"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Domaine modifié"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Options"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Nouveau domaine"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Domaine créé"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Nom du fichier"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Séparateur"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Destinataire(s)"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Indiquer un ou plusieurs destinataires séparés par une ','"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Conserver des copies locales"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr "Transférer les messages et conserver une copie dans votre boite locale"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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"
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Sélectionner un fichier"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Continuer en cas d'erreur"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Ne pas traiter les objets dupliqués comme des erreurs"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Chiffrer les mots de passe"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr "Une boite aux lettres est requise"
|
||||
|
||||
#: admin/lib.py:120
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "Vous n'êtes pas autorisé à importer des domaines"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr "Vous n'êtes pas autorisé à importer des alias de domaine."
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "Adresse"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
msgid "The alias address."
|
||||
msgstr "L'adresse de l'alias"
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "Activé"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Cocher pour activer cet alias"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "liste de distribution"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "transfert"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
msgid "Invalid address"
|
||||
msgstr "Adresse invalide"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Destinataire local {}@{} introuvable"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Ligne invalide : %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "Domaine '%s' inexistant"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "Le nom du domaine"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Cocher pour activer ce domaine"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Ligne invalide"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr "Quota invalide pour le domaine '%s'"
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "Le nom de l'alias"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "cible"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "Le domaine vers lequel cet alias pointe"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Domaine %s inconnu"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Adresse de la boite aux lettres (sans la partie @domain.tld)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Impossible de récuperer l'emplacement de la boite (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, 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)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "Un quota est requis"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr "Le domaine est désactivé"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "Mo"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiques"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr "Domaines et identités"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr "Compteurs globaux"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr "Quantité"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Alias de domaine"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr "Compteurs par domaine"
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Actions"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr "Desactivé"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Administrateurs"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Divers"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Aucun administrateur de domaine défini"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Date de création"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Date de dernière modification"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Alias de boite."
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Transférer automatiquement les messages vers une autre adresse"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Mettre à jour"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Nom complet/Destinataire"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Aide"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Import en cours..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Choisir une valeur"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Utiliser la valeur par défaut du domaine"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Adresse"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Valeur"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Limite"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Utilisation (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Chercher"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "Activé"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "Activée"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr "Lister les domaines"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Ajouter un domaine"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Importer"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Exporter"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Lister les identités"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Lister les quotas"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Ajouter un compte"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Ajouter un alias"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Ajouter un transfert"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Ajouter une liste de distribution"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Voir les identités du domaine"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "Supprimer %s ?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Supprimer cette permission"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Un alias de ce nom existe déjà"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Créer"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Nouvelle liste de distribution"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Liste de distribution créée"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Nouvel alias"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias créé"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Nouveau transfert"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Transfert créé"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Liste de distribution modifiée"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Transfert modifié"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Alias modifié"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "Vous ne pouvez pas supprimer votre propre domaine"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Domaine supprimé"
|
||||
msgstr[1] "Domaines supprimés"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Export d'identités"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Export de domaines"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Requête invalide"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Compte supprimé"
|
||||
msgstr[1] "Comptes supprimés"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "L'objet existe déjà : %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d objets importés avec succès"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Fournir un fichier CSV ou chaque ligne respècte un des formats suivants :\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; nom; quota; activé</em></li>\n"
|
||||
" <li><em>domainalias; nom; domaine cible; activé</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>Le premier élément de chaque ligne est obligatoire et doit être égal à "
|
||||
"l'une des valeurs précédentes.</p>\n"
|
||||
"<p>Vous pouvez utiliser un caractère différent comme séparateur.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Importer des domaines"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Fournir un fichier CSV ou chaque ligne respècte un des formats suivants :\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; identifiant; mot de passe; prénom; nom; activé, groupe; "
|
||||
"addresse; quota; [, domaine, ...]</em></li>\n"
|
||||
"<li><em>alias; addresse; activé; destinataire interne</em></li>\n"
|
||||
"<li><em>forward; addresse; activé; destinataire externe</em></li>\n"
|
||||
"<li><em>dlist; addresse; activée; destinataire; destinataire; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>Le premier élément de chaque ligne est obligatoire et doit être égal à "
|
||||
"l'une des valeurs précédentes.</p>\n"
|
||||
"\n"
|
||||
"<p>Vous pouvez utiliser un caractère différent comme séparateur.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Importer des identités"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Transfert mis à jour"
|
||||
@@ -0,0 +1,54 @@
|
||||
# Modoboa french translation
|
||||
# Copyright (C) 2009-2013
|
||||
# This file is distributed under the same license as the Modoboa package.
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2009-2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: modoboa-1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2011-01-07 10:00+0100\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: FR <tonio@ngyn.org>\n"
|
||||
"Language: Français\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr "Plus de domaine à afficher"
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Ne pas supprimer le répertoire du domaine"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Cette opération supprimera TOUTES les données associées à ce domaine."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
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."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Aucun administrateur de domaine défini"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr "Plus d'identité à afficher"
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Ne pas supprimer le répertoire de la boite aux lettres"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr "Plus de quota à afficher"
|
||||
@@ -0,0 +1,878 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Giancarlo Gaifas <lallo@artiemestieri.tn.it>, 2013
|
||||
# Rocco <mors10@hotmail.com>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2015-10-11 11:48+0000\n"
|
||||
"Last-Translator: Rocco <mors10@hotmail.com>\n"
|
||||
"Language-Team: Italian (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"it/)\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Caselle di posta"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Gestione delle caselle di posta nel filsystem"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
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 filesystem quando vengono "
|
||||
"rinominate o cancellate in Modoboa "
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Proprietario delle caselle postali"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
msgid "The UNIX account who owns mailboxes on the filesystem"
|
||||
msgstr "L'account UNIX a cui appartengono le caselle postali nel filsystem"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr "Quota predefinita per il domini"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Rimozione automatica dell'account"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
msgid "When a mailbox is removed, also remove the associated account"
|
||||
msgstr ""
|
||||
"Quando una casella postale viene rimossa rimuovi anche l'account associato"
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Creazione automatica del domini/casella di posta elettronica"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
msgid "Create a domain and a mailbox when an account is automatically created."
|
||||
msgstr ""
|
||||
"Crea un dominio ed una casella di posta elettronica quando si crea un "
|
||||
"account utente"
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr "Dev'essere un intero positivo"
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr "Amministrazione"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
msgid "Domain administrator"
|
||||
msgstr "Amministratore Dominio"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Domini"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Identità"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Inoltra"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Importazione dell'account fallito (%s): il dominio non esiste"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "La casella di posta %s esiste già"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Importazione account fallito(%s): valore della quota errato"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr "alias del dominio"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Nome utente"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
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"
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Ruolo"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Scegli"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Il livello di permessi che avrà questo utente"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Conferma"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr ""
|
||||
"Inserisci la medesima password che hai inserito sopra, per la verifica."
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Abilitato"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr "Solo i super amministratori possono operare in questa modalità"
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Le password nei due campi non corrispondono"
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "Tu non puoi disabilitare il tuo account"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Quota"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "Il dominio non esiste"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Dominio(i)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Dominio(i) amministrato(i) dall'utente"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Generale"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Posta"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Permessi"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Account aggiornato"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Nuovo account"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Account creato"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "Indirizzo email"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"Indirizzi email alias. Per creare un alias catchall specifica il nome del "
|
||||
"dominio (@domain.tld)."
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Destinatari"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
msgid ""
|
||||
"Addresses this alias will point to. Indicate only one address per input, "
|
||||
"press ENTER to add a new input."
|
||||
msgstr ""
|
||||
"Indirizzi verso il quale questo alias punterà . Indicare un solo indirizzo "
|
||||
"per ogni ingresso , premere INVIO per aggiungere un nuovo input ."
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "Non hai accesso a questo dominio"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Non è stato definito un destinatario"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr "Dominio"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr "Tipo"
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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"
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "Un %s con questo nome esiste già"
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr "dominio"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Crea un amministratore di dominio"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Crea automaticamente un amministratore per questo dominio"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Crea alias"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Crea automaticamente gli alias standard per questo dominio"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Formato non valido"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "L'utente '%s' esiste già"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Dominio modificato"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Opzioni"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Nuovo dominio"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Dominio creato"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Nome del file"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Separatore"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Destinatario(i)"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Indicare uno o più destinatari separati da ','"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Mantieni copie locali"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr ""
|
||||
"Inoltra i messaggi e memorizza le copie nella tua casella di posta locale"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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."
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Seleziona un file"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Continuare in caso di errore"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Non considerare errore gli oggetti duplicati"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Cripta le password"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr "É necessaria una casella"
|
||||
|
||||
#: admin/lib.py:120
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "Non hai i permessi di importare domini"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr "Non hai i permessi di importare gli alias dominio"
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "indirizzo"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
msgid "The alias address."
|
||||
msgstr "Indirizzi Alias."
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "Attivato"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Seleziona per attivare questo alias"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "elenco di smistamento"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "inoltra"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
msgid "Invalid address"
|
||||
msgstr "Indirizzo non valido"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Destinatario locale {}@{} non trovato"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Riga non valida: %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "Il dominio '%s' non esiste"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "nome"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "Il nome del dominio"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Seleziona per attivare questo dominio"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Riga non valida"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr "Valore della quota non valido per il dominio '%s'"
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "Il nome dell'alias"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "destinazione"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "Il dominio a cui punta questo alias"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Dominio sconosciuto %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Indirizzo della casella di posta (senza la parte @dominio.org)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Impossibile recuperare la posizione della casella di posta (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, python-format
|
||||
msgid "Quota is greater than the allowed domain's limit (%dM)"
|
||||
msgstr "La quota è maggiore del limite stabilito per il dominio (%dM)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "È richiesta una quota"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr "il Dominio è disabilitato"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiche"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr "Domini e identità"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr "Contatori globali"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr "Quantità"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Alias del dominio"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr "Contatore per dominio"
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Tag"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Azioni"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr "Disabilitato"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Amministratori"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Miscellanea"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Non è stato definito alcun amministratore di dominio"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Data di creazione"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Data dell'ultima modifica"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Alias delle caselle di posta"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Inoltra automaticamente le e-mail ad un altro indirizzo"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Aggiorna"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Nome completo/Destinatario"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Aiuto"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Importazione..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Scegli un valore"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Usa il valore predefinito"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Indirizzo"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Valore"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Limite"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Utilizzo (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Ricerca"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "Abilitato"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "Abilitata"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr "Lista domini"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Aggiungi dominio"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Importa"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Esporta"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Elenco identità"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Elenco quote"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Aggiungi account"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Aggiungi alias"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Aggiungi inoltro"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Aggiungi elenco di smistamento"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Visualizza le identita del dominio"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "Eliminare %s?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Rimuovi questo permesso"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Un alias con questo nome esiste già"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Crea"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Nuovo elenco di smistamento"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Elenco di smistamento creato"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Nuovo alias"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias creato"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Nuovo inoltro"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Inoltro creato"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Elenco di smistamento modificato"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Inoltro modificato"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Alias modificato"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "Non puoi cancellare il tuo dominio"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Dominio cancellato"
|
||||
msgstr[1] "Domini cancellati"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Identità di esportazione"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Esporta domini"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Richiesta non valida"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Account cancellato"
|
||||
msgstr[1] "Account cancellati"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "L'oggetto esiste già: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d oggetti importati correttamente"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Fornire un file CSV le cui righe rispettino uno dei seguenti formati:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>dominio; nome; quota; abilitato</em></li>\n"
|
||||
" <li><em>aliasdominio; nome; dominio di destinazione; abilitato<em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>Il primo elemento di ogni riga è obbligatorio e deve essere uguale a "
|
||||
"quello dei valori precedenti.</p>\n"
|
||||
"\n"
|
||||
"<p>Come separatore puoi utilizzare un carattere diverso.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Importa domini"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Fornire un file CSV le cui righe rispettino uno dei seguenti formati:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; id utente; password; nome; cognome; abilitato; gruppo; "
|
||||
"indirizzo; quota; [, dominio, ...]</em></li>\n"
|
||||
"<li><em>alias; indirizzo; abilitato; destinatario interno</em></li>\n"
|
||||
"<li><em>forward; indirizzo; abilitato; destinatario esterno</em></li>\n"
|
||||
"<li><em>dlist; indirizzo; abilitato; destinatario; destinatario; ...</em></"
|
||||
"li>\n"
|
||||
"</ul>\n"
|
||||
"<p>Il primo elemento di ogni riga è obbligatorio e deve essere uguale a "
|
||||
"quello dei valori precedenti.</p>\n"
|
||||
"\n"
|
||||
"<p>Come separatore puoi utilizzare un carattere diverso.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Identità di importazione"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Inoltro aggiornato"
|
||||
@@ -0,0 +1,56 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Rocco <mors10@hotmail.com>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2015-10-11 11:19+0000\n"
|
||||
"Last-Translator: Rocco <mors10@hotmail.com>\n"
|
||||
"Language-Team: Italian (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"it/)\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr "Non ci sono altri domini da mostrare"
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Non eliminare la cartella dei domini"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Questa operazione eliminerà TUTTI i dati associati a questo dominio."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
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"
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Non è stato definito un amministratore di dominio"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr "Non ci sono altre identità da mostrare"
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Non eliminare la cartella della casella posta"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr "Non ci sono altre quote da mostrare"
|
||||
@@ -0,0 +1,897 @@
|
||||
# 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 <buddha@cryptolab.net>, 2014
|
||||
# TuxBrother <vrijwilligerswerk@wij.rs>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2014-12-31 11:37+0000\n"
|
||||
"Last-Translator: TuxBrother <vrijwilligerswerk@wij.rs>\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"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Mailboxen"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Pas mailboxen op het bestandssysteem aan"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Eigenaar van de mailboxen"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
msgid "The UNIX account who owns mailboxes on the filesystem"
|
||||
msgstr ""
|
||||
"De UNIX account die de rechten heeft tot de mailboxen op het bestandssysteem"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr "Standaard domein quota"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Automatish een account verwijderen"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
msgid "When a mailbox is removed, also remove the associated account"
|
||||
msgstr ""
|
||||
"Als een mailbox word verwijderd, verwijder dan ook de bijbehorende account"
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Domein en mailbox automatisch aanmaken"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr "Dit moet een positive integer zijn."
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr "Administratie"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
#, fuzzy
|
||||
#| msgid "Create a domain administrator"
|
||||
msgid "Domain administrator"
|
||||
msgstr "Maak een domein administrator aan"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Domeinen"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Identiteiten"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Doorsturen"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Accounts importeren mislukt (%s): domein bestaat niet"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "Mailbox %s bestaat al"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Account import is mislukt (%s): verkeerd quotum waarde"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr "domein alias"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Gebruikersnaam"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
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."
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Regel"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Kiezen"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Welk niveau van rechten deze gebruiker zal hebben"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Wachtwoord"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Bevestiging"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Herhaal wachtwoord (voor verificatie)"
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Actief"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "De wachtwoorden komen niet overeen."
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "U kunt uw eigen account niet uitschakelen"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Quota"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias(sen)"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "Domein bestaat niet"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Domein(en)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Domein(en) die gebruiker mag beheren"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Algemeen"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Mail"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Rechten"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Account aangepast"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Nieuwe account"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Account aangemaakt"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "Email adres"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The alias address (without the domain part). For a 'catch-all' address, "
|
||||
#| "just enter an * character."
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"Het alias adres (zonder het domein deel). Voor een 'catch-all' adres, vul "
|
||||
"een * in."
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Ontvangers"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Mailbox(es) this alias will point to. Indicate only one address per "
|
||||
#| "input, press ENTER to add a new input."
|
||||
msgid ""
|
||||
"Addresses 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."
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "U heeft geen toegang tot dit domein"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Geen ontvanger opgegeven"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr "Domein"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "Een %s met deze naam bestaat al"
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr "domein"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Maak een domein administrator aan"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Automatisch een administrator aanmaken voor dit domein"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Naam"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Aliassen aanmaken"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Automatisch een standaard alias voor dit domein aanmaken"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Verkeerd formaat"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "Gebruiker '%s' bestaat al"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Domein gewijzigd"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Opties"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Nieuw domein"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Domein aangemaakt"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Bestandsnaam"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Scheidingsteken"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Ontvanger(s)"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Geef een of meer ontvangers op, gescheiden door een komma"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Lokale kopie behouden"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr "Stuur berichten door en sla een kopie op in uw mailbox"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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."
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Bestand selecteren"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Doorgaan als er een fout optreed"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Zie duplicaten niet als fout"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Versleutel wachtwoorden"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr "Een mailbox is benodigd"
|
||||
|
||||
#: admin/lib.py:120
|
||||
#, fuzzy
|
||||
#| msgid "You can't delete your own domain"
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "U kunt uw eigen domein niet verwijderen"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "adres"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
#, fuzzy
|
||||
#| msgid "The alias name"
|
||||
msgid "The alias address."
|
||||
msgstr "De alias naam"
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "actief"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Aanvinken om deze alias te activeren"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "distributie lijst"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "doorsturen"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
#, fuzzy
|
||||
#| msgid "Invalid request"
|
||||
msgid "Invalid address"
|
||||
msgstr "Ongeldig verzoek"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
#, fuzzy
|
||||
#| msgid "Local recipient %s not found"
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Lokale ontvanger %s niet gevonden"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Ongeldige regel: %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "Domein '%s' bestaat niet"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "naam"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "De domeinnaam"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Aanvinken om dit domein te activeren"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Verkeerde regel"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr "Verkeerde quota waarde voor domein '%s'"
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "De alias naam"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "doel"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "De domein alias verwijst naar"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Onbekend domein %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Mailbox adres (zonder het @domein.naam deel)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Mislukt om de mailbox locatie te verkijgen (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, python-format
|
||||
msgid "Quota is greater than the allowed domain's limit (%dM)"
|
||||
msgstr "Quota is groter dan de maximaal toegestane domein limiet (%dM)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "Een quota is vereist"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr "Domein is gedeactiveerd"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Statistieken"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr "Domeinen en identiteiten"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr "Globale statistieken"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr "Hoeveelheid"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Domein aliassen"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr "Statistieken per domein"
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Labels"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Acties"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr "uitgeschakeld"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Administrators"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Diversen"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Geen domein administrator toegewezen"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Datum van aanmaken"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Laatst gewijzigd"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Mailbox aliassen"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Automatisch mails doorsturen naar een ander adres"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Toepassen"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Volledige naam/Ontvanger"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Help"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Importeren..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Kies een waarde"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Gebruik de standaard waarde van dit domein"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Adres"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Waarde"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Limiet"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Gebruik (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Zoeken"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "geactiveerd_m"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "geactiveerd_f"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr "Weergeef domeinen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Domein toevoegen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Importeren"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Exporteren"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Weergeef identiteiten"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Weergeef quota's"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Account aanmaken"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Alias toevoegen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Doorsuurregel toevoegen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Distributielijst toevoegen"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Weergeef de identiteiten van dit domein"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "Verwijder %s?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Deze bevoegdheid verwijderen"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Een alias met deze naam bestaat al"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Aanmaken"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Nieuwe distributie lijst"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Distributielijst aangemaakt"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Nieuwe alias"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias aangemaakt"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Nieuwe doorstuurregel"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Doorstuurregel aangemaakt"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Distributielijst aangepast"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Doorstuurregel aangepast"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Alias aangepast"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "U kunt uw eigen domein niet verwijderen"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Domeinen verwijderd"
|
||||
msgstr[1] "Domeinen verwijderd"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Identiteiten exporteren"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Exporteer domeinen"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Ongeldig verzoek"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Account verwijderd"
|
||||
msgstr[1] "Accounts verwijderd"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "Object bestaat al: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d objecten successvol geimporteerd"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Lever een CSV bestand en zorg dat de regels voldoen aan een van de volgende "
|
||||
"formaten:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>domain; name; quota; enabled</em></li>\n"
|
||||
"<li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
"%s\n"
|
||||
"</ul>\n"
|
||||
"<p>Het eerste element van elke regel is verplicht en moet gelijk zijn aan "
|
||||
"een van de vorige waarden.</p>\n"
|
||||
"<p>U kunt een eigen scheidingsteken gebruiken.</p>\n"
|
||||
"<p>Let op! Zorg dat het 'line-encoding format' Unix is - anders gaat het "
|
||||
"importeren mis</p>\n"
|
||||
"\n"
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Importeer domeinen"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Lever een CSV bestand en zorg dat de regels voldoen aan een van de volgende "
|
||||
"formaten:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>Het eerste element van elke regel is verplicht en moet gelijk zijn aan "
|
||||
"een van de vorige waarden.</p>\n"
|
||||
"<p>U kunt een eigen scheidingsteken gebruiken.</p>\n"
|
||||
"<p>Let op! Zorg dat het 'line-encoding format' Unix is - anders gaat het "
|
||||
"importeren mis</p>\n"
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Identiteiten importeren"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Doorstuuradres aangepast"
|
||||
@@ -0,0 +1,59 @@
|
||||
# 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 <vrijwilligerswerk@wij.rs>, 2014
|
||||
# TuxBrother <vrijwilligerswerk@wij.rs>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2014-12-31 11:42+0000\n"
|
||||
"Last-Translator: TuxBrother <vrijwilligerswerk@wij.rs>\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"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr "Geen domein meer om te weergeven"
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "De map van dit domein niet verwijderen (Zal de data ervan behouden)"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
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?"
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
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."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Geen administrator toegewezen"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr "Geen identiteiten meer om te weergeven"
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Verwijder de map van deze mailbox niet (zal de data ervan behouden)"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr "Geen quota meer om te weergeven"
|
||||
@@ -0,0 +1,871 @@
|
||||
# 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 <paulino@michelazzo.com.br>, 2014
|
||||
# Rafael Barretto Alves <ch3yd@hotmail.com>, 2013,2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2015-09-09 08:30+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/tonio/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"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Caixas de correios"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Tratar caixas de mensagens no sistema de arquivos."
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Proprietário de caixas de mensagens"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
msgid "The UNIX account who owns mailboxes on the filesystem"
|
||||
msgstr "A conta UNIX que possui caixas de mensagens no sistema de arquivos"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr "Cota padrão do domínio"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
msgid ""
|
||||
"Default quota (in MB) applied to freshly created domains with no value "
|
||||
"specified. A value of 0 means no quota."
|
||||
msgstr ""
|
||||
"Cota padrão (em MB) aplicada para novos domínios sem nenhum valor "
|
||||
"especificado. Um valor de 0 indica que não existe cota."
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Remoção automática da conta"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
msgid "When a mailbox is removed, also remove the associated account"
|
||||
msgstr ""
|
||||
"Quando uma caixa de correio é removida, também remove a conta associada"
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Criação automática de domínio/caixa de correio"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr "Deve ser um inteiro positivo"
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr "Administração"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
msgid "Domain administrator"
|
||||
msgstr "Administrador de domínio"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Domínios"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Identidades"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Encaminhar"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Falha ao importar a conta (%s): domínio não existe"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "A caixa %s já existe"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Falha na importação de conta (%s): valor de cota errado"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr "alias de domínio"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Nome de usuário"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
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."
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Papel"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Escolher"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Qual nível de permissão terá esse usuário"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Senha"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Confirmação"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Para verificação, digite a mesma senha que a anterior."
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Ativado"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr "Apenas super administradores estão liberados para este modo"
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Os dois campos de senha não coincidiram."
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "Você não pode desabilitar seu própria conta"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Cota"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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 ""
|
||||
"Cota 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)."
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias(es)"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "Domínio não existe"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Domínio(s)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Domínio(s) que o usuário administra"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Geral"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Correio"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Permissões"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Conta atualizada"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Nova conta"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Conta criada"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "Endereço de e-mail"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Destinatários"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
msgid ""
|
||||
"Addresses this alias will point to. Indicate only one address per input, "
|
||||
"press ENTER to add a new input."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "Você não tem acesso a esse domínio"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Nenhum destinatário definido"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr "Domínio"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr "Tipo"
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
msgid ""
|
||||
"Default quota in MB applied to mailboxes. Leave empty to use the default "
|
||||
"value."
|
||||
msgstr ""
|
||||
"Cota padrão em MB aplicada para caixas de mensagens. Deixe em branco para "
|
||||
"usar o valor padrão."
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "Já existe um %s com este nome"
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr "domínio"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Criar um administrador de domínio"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Criar automaticamente um administrador para este domínio"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Criar alias"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Criar automaticamente aliases padrão para este domínio"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Formato inválido"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "O usuário '%s' já existe"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Domínio alterado"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Opções"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Novo domínio"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Domínio criado"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Nome do arquivo"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Separador"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Destinatário(s)"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Indique um ou mais destinatários separados por uma ','"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Manter cópias locais"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr "Encaminhar mensagens e armazenar cópias em sua caixa de correio local"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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."
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Selecione um arquivo"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Continuar em caso de erro"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Não tratar como erro objetos duplicados"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Criptografar senhas"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr "Um caixa de mensagens é obrigatória"
|
||||
|
||||
#: admin/lib.py:120
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "Você não tem permissão para importar domínios"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr "Você não tem permissão para importar aliases de domínio."
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "endereço"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
msgid "The alias address."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "ativado"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Verificar para ativar o alias"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "lista de distribuição"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "encaminhar"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
msgid "Invalid address"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Destinatário local {}@{} não encontrado"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Linha inválida: %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "O domínio '%s' não existe"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "nome"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "Nome do domínio"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Marque para ativar esse domínio"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Linha inválida"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr "Valor de cota inválido para o domínio '%s'"
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "Nome de alias"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "alvo"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "Esse alias aponta para o domínio"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Domínio desconhecido %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Endereço da caixa de correio (sem a parte @meu.dominio)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Falha ao recuperar a localização da caixa de mensagens (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, python-format
|
||||
msgid "Quota is greater than the allowed domain's limit (%dM)"
|
||||
msgstr "A cota é maior que o permitido pelo limite do domínio (%dM)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "Uma cota é requerida"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr "Domínio está desabilitado"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Estatísticas"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr "Domínios e identidades"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr "Contadores globais"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr "Quantidade"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Alias de domínios"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr "Contadores por domínios"
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Ações"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr "desabilitado"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Administradores"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Diversos"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Nenhum administrador de domínio definido"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Data de criação"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Data da última modificação"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Alias de caixas de correio"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Encaminhar e-mails automaticamente para outro endereço"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Atualizar"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Nome completo/Destinatário"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Ajuda"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Importando..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Escolher um valor"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Usar valor padrão do domínio"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Endereço"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Limite"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Uso (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Busca"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "Ativado"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "Ativada"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr "Listardomínios"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Adicionar domínio"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Exportar"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Listar identidades"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Listar quotas"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Adicionar conta"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Adicionar alias"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Adicionar encaminhamento"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Adicionar lista de distribuição"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Ver as identidades de domínios"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "Remover %s?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Remover essa persmissão"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Um alias para esse nome já existe"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Criar"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Nova lista de distribuição"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Lista de distribuição criada"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Novo alias"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias criado"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Novo encaminhamento"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Encaminhamento criado"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Lista de distribuição modificada"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Encaminhamento modificado"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Alias modificado"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "Você não pode deletar seu próprio domínio"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Domínio deletado"
|
||||
msgstr[1] "Domínios deletados"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Exportar identidades"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Exportar domínios"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Solicitação inválida"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Conta deletada"
|
||||
msgstr[1] "Contas deletadas"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "O objeto já existe: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d objetos importados com sucesso"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Forneça um arquivo CSV onde as linhas respeitam um dos seguintes formatos:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; cota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>O primeiro elemento de cada linha é mandatório e deve ser igual a um dos "
|
||||
"valores indicados.</p>\n"
|
||||
"<p>Você pode usar um caractere diferente como separador.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Importar domínios"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Forneça um arquivo CSV onde as linhas respeitam um dos seguintes formatos:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; cota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>O primeiro elemento de cada linha é mandatório e deve ser igual a um dos "
|
||||
"valores indicados.</p>\n"
|
||||
"\n"
|
||||
"<p>Você pode usar um caractere diferente como separador.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Importar identidades"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Encaminhamento atualizado"
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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 <paulino@michelazzo.com.br>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2015-08-10 20:19+0000\n"
|
||||
"Last-Translator: Rafael Barretto Alves <ch3yd@hotmail.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/tonio/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"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr "Nenhum domínio a mais para mostrar"
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Não remova o diretório de domínio"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Esta operação removerá TODOS os dados associados com este domínio."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
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."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Nenhum administrador de domínio definido"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr "Nenhuma identidade a mais para mostrar"
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Não remova o diretório de caixas de mensagens"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr "Nenhuma quota a mais para mostrar"
|
||||
@@ -0,0 +1,873 @@
|
||||
# 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 <dduponchelle@gmail.com>, 2013
|
||||
# lusitan <lusitan@hushmail.com>, 2013
|
||||
# Mike C. <miguelmclara@gmail.com>, 2012
|
||||
# Mike C. <miguelmclara@gmail.com>, 2013-2014
|
||||
# Sandra Ribeiro <sandrarib@gmail.com>, 2012-2013
|
||||
# Sandra Ribeiro <sandrarib@gmail.com>, 2012
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2014-12-29 12:51+0000\n"
|
||||
"Last-Translator: Mike C. <miguelmclara@gmail.com>\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"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Caixas de Correio"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Lidar com caixas de correio no sistema de ficheiros"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Dono das caixas de correio"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr "Quota pré-definida para o domínio"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Remoção automática de conta"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Criação automatica de domino/caixa de correio"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr "Tem de ser um inteiro, positivo"
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr "Administração"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
#, fuzzy
|
||||
#| msgid "Create a domain administrator"
|
||||
msgid "Domain administrator"
|
||||
msgstr "Criar um administrador de domínio"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Domínios"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Identidades"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Reencaminhar"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Importação da conta falhou (%s): domínio não existe"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "Caixa de correio %s já existe"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Importação da conta falhou (%s): valor para quota inválido"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr "'Alias' de domínio"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Nome de Utilizador"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
msgid ""
|
||||
"The user's name. Must be a valid e-mail address for simple users or "
|
||||
"administrators with a mailbox."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Papel"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Escolher"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Que nível de permissões terá o utilizador"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Confirmação"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Repita a password acima, para verificação."
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Ativo"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Os dois campos de password não são idênticos."
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "Não pode desativar a sua própria conta"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Quota"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias(es)"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "O domínio não existe"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Domínio(s)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Domínio(s) administrado pelo utilizador"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Geral"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Correio"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Permissões"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Conta actualizada"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Nova conta"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Conta criada"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "Endereço de e-mail"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The alias address (without the domain part). For a 'catch-all' address, "
|
||||
#| "just enter an * character."
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"O endereço do alias (sem a parte do domínio). Para um endereço 'cath-all', "
|
||||
"digite apenas o caractere *"
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Destinatários"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Mailbox(es) this alias will point to. Indicate only one address per "
|
||||
#| "input, press ENTER to add a new input."
|
||||
msgid ""
|
||||
"Addresses 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."
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "Não tem acesso a este domínio"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Sem destinatário definido"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr "Domínio"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr "Tipo"
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "Já existe um(a) %s com este nome. "
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr "domínio"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Criar um administrador de domínio"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Criar automaticamente um administrador para este domínio"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr " Criar aliases"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Criar automaticamente aliases para este domínio"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Formato inválido"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "O utilizador '%s' já existe"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Domínio alterado"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Opções"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Novo domínio"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Domínio criado"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Nome do ficheiro"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Separador"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Destinatário(s)"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Indicar um ou mais destinatários separados por ','"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Conservar cópias locais"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr ""
|
||||
"Reencaminhar mensagens e armazenar cópias na sua caixa de correio local"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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."
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Escolha um ficheiro"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Continua com erro"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Não tratar objetos duplicados como erro"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Passwords encriptadas"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr "É necessária uma caixa de correio"
|
||||
|
||||
#: admin/lib.py:120
|
||||
#, fuzzy
|
||||
#| msgid "You can't delete your own domain"
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "Não é possível eliminar o seu próprio domínio"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "endereços"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
#, fuzzy
|
||||
#| msgid "The alias name"
|
||||
msgid "The alias address."
|
||||
msgstr "O nome do 'alias'"
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "ativo"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Marcar para ativar este alias"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "lista de distribuição"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "reencaminhar"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
#, fuzzy
|
||||
#| msgid "Invalid request"
|
||||
msgid "Invalid address"
|
||||
msgstr "Pedido inválido"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
#, fuzzy
|
||||
#| msgid "Local recipient %s not found"
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "O destinatário local %s não foi encontrado"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Linha inválida: %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "O domínio '%s' não existe"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "nome"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "O nome do domínio"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Marcar para ativar este domínio"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Linha inválida"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr "Valor de quota inválido para o dominio '%s'"
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "O nome do 'alias'"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "alvo"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "O domínio para o qual este alias irá apontar"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Domínio desconhecido: %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Endereços das caixas de correio (sem a parte @domain.tld)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Falha ao recuperar a localização da caixa de correio (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, python-format
|
||||
msgid "Quota is greater than the allowed domain's limit (%dM)"
|
||||
msgstr "A quota excede o limite permitido pelo domínio (%dM)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "É necessário uma quota"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr "O dominio está inativo"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Estatísticas"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr "Domínios e identidades"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr "Contadores globais"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr "Quantidade"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Aliases de domínio"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr "Contadores por-domínio"
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Ações"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr "inativo"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Administradores"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Vários"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Nenhum administrador de domínio definido"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Data de criação"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Data da última modificação"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Aliases para caixas de correio"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Reenviar automaticamente e-mails para outro endereço"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Actualizar"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Nome Completo / Destinatário"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Ajuda"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "A importar..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Escolha um valor"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Usar um valor padrão de domínio"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Endereço"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Limite"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Utilização (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Procurar"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "enabled_m"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "enabled_f"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr "Listar domínios"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Adicionar domínio"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Exportar"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Listar identidades"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Listar as quotas"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Adicionar conta"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Adicionar 'alias'"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Adicionar reencaminhamento"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Adicionar lista de distribuição"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Visualizar as identidades do domínio"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "Eliminar %s?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Remover esta permissão"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Já existe um 'alias' com este nome"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Criar"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Nova lista de distribuição"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "A lista de distribuição foi criada"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Novo 'alias'"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias criado"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Novo reencaminhamento"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Reencaminhamento criado"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Lista de distribuição modificada"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Reencaminhamento modificado"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "'Alias' modificado"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "Não é possível eliminar o seu próprio domínio"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Domínio criado"
|
||||
msgstr[1] "Domínios eliminados"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Exportar identidades"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Exportar domínios"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Pedido inválido"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Conta eliminada"
|
||||
msgstr[1] "Contas eliminadas"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "Este objeto já existe: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d objetos importados com sucesso"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Importar domínios"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Importar identidades"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Reencaminhamento atualizado"
|
||||
@@ -0,0 +1,61 @@
|
||||
# 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 <lusitan@hushmail.com>, 2013
|
||||
# lusitan <lusitan@hushmail.com>, 2013
|
||||
# Mike C. <miguelmclara@gmail.com>, 2012
|
||||
# Mike C. <miguelmclara@gmail.com>, 2012
|
||||
# Mike C. <miguelmclara@gmail.com>, 2014
|
||||
# Sandra Ribeiro <sandrarib@gmail.com>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2014-12-29 12:08+0000\n"
|
||||
"Last-Translator: Mike C. <miguelmclara@gmail.com>\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"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr "Não existem mais dominios para mostrar"
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Não excluir o diretório do domínio"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
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."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
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."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Não está definido nenhum administrador para o domínio"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr "Não existem mais identidades para mostrar"
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Não excluir o diretório da caixa de correio"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr "Não existem mais quotas para mostrar"
|
||||
@@ -0,0 +1,871 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2013-12-03 09:35+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Russian (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"ru/)\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"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"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Почтовые ящики"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Обрабатывать почтовые ящики на диске"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Rename or remove mailboxes on the filesystem when they get renamed or "
|
||||
"removed within Modoboa"
|
||||
msgstr ""
|
||||
"Удалять или переименовывать почтовые ящики на диске, если они удалены или "
|
||||
"переименованы в Modoboa"
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Почтовые ящики закончились"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
msgid "The UNIX account who owns mailboxes on the filesystem"
|
||||
msgstr "UNIX аккаунт владельца почтового ящика на диске"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
msgid ""
|
||||
"Default quota (in MB) applied to freshly created domains with no value "
|
||||
"specified. A value of 0 means no quota."
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Автоматическое удаление аккаунта"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
msgid "When a mailbox is removed, also remove the associated account"
|
||||
msgstr "При удалении почтового ящика, так же удалять и аккаунт владельца"
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
#, fuzzy
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Домен создан"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
msgid "Create a domain and a mailbox when an account is automatically created."
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr ""
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr ""
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
#, fuzzy
|
||||
#| msgid "Create a domain administrator"
|
||||
msgid "Domain administrator"
|
||||
msgstr "Создание администратора домена"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Домены"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Пользователи"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Перенаправленые"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Ошибка импорта аккаунта (%s): домен должен существовать "
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "Почтовый ящик %s существует"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, fuzzy, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Ошибка импорта аккаунта (%s): домен должен существовать "
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Логин пользователя"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
msgid ""
|
||||
"The user's name. Must be a valid e-mail address for simple users or "
|
||||
"administrators with a mailbox."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Роль"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Выбрать"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Разрешения для этого пользователя"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Пароль"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Подтверждение"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Введите такой же пароль как выше. Для проверки."
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Разрешено"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Пароли не совпадают"
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "Вы не можете запретить собственный аккаунт"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "Е-майл"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Квота"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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 ""
|
||||
"Квота в мегабайтах для этого почтового ящика. Определите собственное "
|
||||
"значение или используйте значение по умолчанию для родительского домена. "
|
||||
"Оставьте пустым для неограниченного значения. (Не разрешено администраторам "
|
||||
"домена)"
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Синоним(ы)"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)"
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "Домен не существует"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Домен(ы)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Домен(ы) администрируемые пользователем"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Основные"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Почта"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Права"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "аккаунт изменен"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Новый аккаунт"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Аккаунт создан"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "Е-майл адрес"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The alias address (without the domain part). For a 'catch-all' address, "
|
||||
#| "just enter an * character."
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"Адреса синонимов (без доменной части). Для указания адреса 'для всех' "
|
||||
"введите символ *"
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Получатели"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Mailbox(es) this alias will point to. Indicate only one address per "
|
||||
#| "input, press ENTER to add a new input."
|
||||
msgid ""
|
||||
"Addresses this alias will point to. Indicate only one address per input, "
|
||||
"press ENTER to add a new input."
|
||||
msgstr ""
|
||||
"Этот синоним почтового ящика. Вводите один адрес за раз. Нажмите ENTER для "
|
||||
"добавления."
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "Вы не имеете права доступа к этому домену"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Получатель не определен"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
msgid ""
|
||||
"Default quota in MB applied to mailboxes. Leave empty to use the default "
|
||||
"value."
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
msgid ""
|
||||
"Alias(es) of this domain. Indicate only one name per input, press ENTER to "
|
||||
"add a new input."
|
||||
msgstr ""
|
||||
"Синоним(ы) этого домена. Вводите одно имя за раз. Нажмите ENTER для "
|
||||
"добавления."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Создание администратора домена"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Автоматически создаст администратора для этого домена"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Логин"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
msgid ""
|
||||
"The administrator's name. Don't include the domain's name here, it will be "
|
||||
"automatically appended."
|
||||
msgstr ""
|
||||
"Имя администратора. Не включайте имя домена оно будет добавлено "
|
||||
"автоматически."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Создание синонимов"
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Автоматически создает стандартные синонимы для этого домена"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Неверный формат"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "Пользователь '%s' уже существует"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Домен изменен"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Опции"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Новый домен"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Домен создан"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Имя файла"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Разделитель"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Получатели"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Укажите одного или нескольких получателей, разделенных запятой ','"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Сохранить локальную копию"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr ""
|
||||
"Перенаправление сообщения, и сохранение копии в вашем локальном почтовом "
|
||||
"ящике"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
msgid ""
|
||||
"You can't define a forward to a local destination. Please ask your "
|
||||
"administrator to create an alias instead."
|
||||
msgstr ""
|
||||
"Вы не можете определить перенаправление на локальный адрес. Пожалуйста, "
|
||||
"попросите администратора создать синоним"
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Выберите файл"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Продолжать при ошибке"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Не исправлять дублирующийся объект при ошибке"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Шифровать пароль"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
msgid "Check this option if passwords contained in your file are not crypted"
|
||||
msgstr "Выберите эту опцию если пароль в вашем файле не зашифрован "
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr ""
|
||||
|
||||
#: admin/lib.py:120
|
||||
#, fuzzy
|
||||
#| msgid "You can't delete your own domain"
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "Вы не можете удалить собственный домен"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "адрес"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
#, fuzzy
|
||||
#| msgid "The alias name"
|
||||
msgid "The alias address."
|
||||
msgstr "Имя синонима"
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "Разрешен"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Отметить для активации синонима"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "Список рассылки"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "Перенаправление"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "Синоним"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
#, fuzzy
|
||||
#| msgid "Invalid request"
|
||||
msgid "Invalid address"
|
||||
msgstr "Ошибочный запрос"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
#, fuzzy
|
||||
#| msgid "Local recipient %s not found"
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Локальный получатель %s не найден"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Неверная строка %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "Домен '%s' не существует"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "имя"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "Имя домена"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Отметить для активации этого домена"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Ошибочная строка"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "Имя синонима"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "адресат"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "Домен этого синонима указывает на"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Неизвестный домен %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Адрес почтового ящика (без @domain.tld)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Ошибка получения места находжения почтового ящика (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, python-format
|
||||
msgid "Quota is greater than the allowed domain's limit (%dM)"
|
||||
msgstr "Квота больше чем разрешено на уровне домена (%dM)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "Требуется квота"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
#, fuzzy
|
||||
msgid "Domain is disabled"
|
||||
msgstr "Домен удален"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "Мб"
|
||||
|
||||
#: admin/templates/admin/domain_options_form.html:7
|
||||
msgid "You can't create a new domain administrator"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Статистика"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#, fuzzy
|
||||
msgid "Domains and identities"
|
||||
msgstr "Список пользователей"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
#, fuzzy
|
||||
msgid "Quantity"
|
||||
msgstr "Карантин"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Синонимы доменов"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr ""
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Теги"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Действие"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
#, fuzzy
|
||||
msgid "disabled"
|
||||
msgstr "Разрешен"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Администраторы"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Прочее"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Администратор домена не определен"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Дата создания"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Дата последней модификации"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Синонимы почтового ящика"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Автоматически перенаправлять письма на другой адрес"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Обновление"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Полное имя/получатель"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Подсказка"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Импорт..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Выбрать значение"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Используются значения домена по умолчанию "
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Адрес"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Значение"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Лимит"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "использование (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Поиск"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "enabled_m"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "enabled_f"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
#, fuzzy
|
||||
msgid "List domains"
|
||||
msgstr "Список квот"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Добавить домен"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Импорт"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Экспорт"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Список пользователей"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Список квот"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Добавить аккаунт"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Добавить синоним"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Добавить пересылку"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Добавить список рассылки"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Информация о домене"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "Удалить %s?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Удалить это разрешение"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Синоним с таким именем уже есть"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Создать"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Новый список рассылки"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Список рассылки создан"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Новый синоним"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Синоним создан"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Новая пересылка"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Пересылка создана"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Список рассылки изменен"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Пересылка изменена"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Синоним изменен"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "Вы не можете удалить собственный домен"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Домен удален"
|
||||
msgstr[1] "Домена удалено"
|
||||
msgstr[2] "Доменов удалено"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Экспорт пользователя"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Экспорт доменов"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Ошибочный запрос"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Аккаунт удален"
|
||||
msgstr[1] "Аккаунта удалено"
|
||||
msgstr[2] "Аккаунтов удалено"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "Объект уже существует: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d объектов импортировано"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Импорт доменов"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Импорт информации о пользователях"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Перенаправление обновлено"
|
||||
@@ -0,0 +1,56 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2013-12-03 09:35+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Russian (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"ru/)\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"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"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Не удаляйте каталог домена"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Эта операция удалит ВСЕ данные, связанные с этим доменом."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
"Эта операция удалит ВСЕ данные, связанные с этим доменом, за исключением "
|
||||
"аккаунтов."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Не указан администратор домена"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Не удаляйте каталог почтовых ящиков"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,889 @@
|
||||
# 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 <martin.jens.persson@gmail.com>, 2014
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2013
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2013,2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 18:24+0100\n"
|
||||
"PO-Revision-Date: 2015-01-13 15:18+0000\n"
|
||||
"Last-Translator: Olle Gustafsson <olle@dalnix.se>\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"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin/app_settings.py:54 admin/templates/admin/editdomainform.html:25
|
||||
msgid "Mailboxes"
|
||||
msgstr "Brevlådor"
|
||||
|
||||
#: admin/app_settings.py:57
|
||||
msgid "Handle mailboxes on filesystem"
|
||||
msgstr "Hantera brevlådor på filsystem"
|
||||
|
||||
#: admin/app_settings.py:60
|
||||
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"
|
||||
|
||||
#: admin/app_settings.py:66
|
||||
msgid "Mailboxes owner"
|
||||
msgstr "Brevlådans ägare"
|
||||
|
||||
#: admin/app_settings.py:69
|
||||
msgid "The UNIX account who owns mailboxes on the filesystem"
|
||||
msgstr "Den UNIX-konto som äger brevlådor på filsystemet"
|
||||
|
||||
#: admin/app_settings.py:74
|
||||
msgid "Default domain quota"
|
||||
msgstr "Standard domän kvota"
|
||||
|
||||
#: admin/app_settings.py:77
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:83
|
||||
msgid "Automatic account removal"
|
||||
msgstr "Automatisk konto borttagning"
|
||||
|
||||
#: admin/app_settings.py:86
|
||||
msgid "When a mailbox is removed, also remove the associated account"
|
||||
msgstr "När en brevlåda raderas, radera också tillhörande konto"
|
||||
|
||||
#: admin/app_settings.py:90
|
||||
msgid "Automatic domain/mailbox creation"
|
||||
msgstr "Automatisk skapande av domän/brevlåda"
|
||||
|
||||
#: admin/app_settings.py:93
|
||||
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."
|
||||
|
||||
#: admin/app_settings.py:139 admin/forms/account.py:239
|
||||
#: admin/forms/domain.py:77
|
||||
msgid "Must be a positive integer"
|
||||
msgstr "Måste vara ett positivt heltal"
|
||||
|
||||
#: admin/app_settings.py:149
|
||||
msgid "Administration"
|
||||
msgstr "Administration"
|
||||
|
||||
#: admin/callbacks.py:46
|
||||
#, fuzzy
|
||||
#| msgid "Create a domain administrator"
|
||||
msgid "Domain administrator"
|
||||
msgstr "Skapa en domän administratör"
|
||||
|
||||
#: admin/callbacks.py:75 admin/templates/admin/domain_statistics.html:30
|
||||
#: admin/templates/admin/domains.html:3
|
||||
msgid "Domains"
|
||||
msgstr "Domäner"
|
||||
|
||||
#: admin/callbacks.py:85 admin/templates/admin/domain_statistics.html:36
|
||||
#: admin/templates/admin/domain_statistics.html:50
|
||||
#: admin/templates/admin/identities.html:5
|
||||
msgid "Identities"
|
||||
msgstr "Konton"
|
||||
|
||||
#: admin/callbacks.py:100 admin/templates/admin/forward.html:2
|
||||
msgid "Forward"
|
||||
msgstr "Vidarebefordra"
|
||||
|
||||
#: admin/callbacks.py:163
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): domain does not exist"
|
||||
msgstr "Konto import misslyckades (%s): domänen existerar inte"
|
||||
|
||||
#: admin/callbacks.py:173 admin/forms/account.py:257
|
||||
#, python-format
|
||||
msgid "Mailbox %s already exists"
|
||||
msgstr "Brevlåda %s finns redan"
|
||||
|
||||
#: admin/callbacks.py:181
|
||||
#, python-format
|
||||
msgid "Account import failed (%s): wrong quota value"
|
||||
msgstr "Importering av konto misslyckades (%s): Fel kvota värde"
|
||||
|
||||
#: admin/callbacks.py:216 admin/forms/domain.py:94
|
||||
msgid "domain alias"
|
||||
msgstr "domän alias"
|
||||
|
||||
#: admin/forms/account.py:30 admin/templates/admin/editdomainform.html:13
|
||||
msgid "Username"
|
||||
msgstr "Användarnamn"
|
||||
|
||||
#: admin/forms/account.py:32
|
||||
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."
|
||||
|
||||
#: admin/forms/account.py:37
|
||||
msgid "Role"
|
||||
msgstr "Roll"
|
||||
|
||||
#: admin/forms/account.py:38 admin/forms/account.py:75
|
||||
msgid "Choose"
|
||||
msgstr "Välj"
|
||||
|
||||
#: admin/forms/account.py:39
|
||||
msgid "What level of permission this user will have"
|
||||
msgstr "Vilken nivå av behörighet den här användaren har"
|
||||
|
||||
#: admin/forms/account.py:42
|
||||
msgid "Password"
|
||||
msgstr "Lösenord"
|
||||
|
||||
#: admin/forms/account.py:45
|
||||
msgid "Confirmation"
|
||||
msgstr "Bekräftelse"
|
||||
|
||||
#: admin/forms/account.py:48
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Ange samma lösenord som ovan för verifiering."
|
||||
|
||||
#: admin/forms/account.py:66
|
||||
msgid "Enabled"
|
||||
msgstr "Aktiverad"
|
||||
|
||||
#: admin/forms/account.py:141
|
||||
msgid "Only super administrators are allowed for this mode"
|
||||
msgstr ""
|
||||
|
||||
#: admin/forms/account.py:150
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Dessa två lösnordsfält matchar inte."
|
||||
|
||||
#: admin/forms/account.py:156
|
||||
msgid "You can't disable your own account"
|
||||
msgstr "Du kan inte inaktivera ditt eget konto"
|
||||
|
||||
#: admin/forms/account.py:170
|
||||
msgid "E-mail"
|
||||
msgstr "E-post"
|
||||
|
||||
#: admin/forms/account.py:172 admin/forms/domain.py:35
|
||||
msgid "Quota"
|
||||
msgstr "Kvot"
|
||||
|
||||
#: admin/forms/account.py:174
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:182 admin/forms/domain.py:43
|
||||
#: admin/templates/admin/domains.html:26
|
||||
msgid "Alias(es)"
|
||||
msgstr "Alias"
|
||||
|
||||
#: admin/forms/account.py:185
|
||||
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)."
|
||||
|
||||
#: admin/forms/account.py:248 admin/forms/account.py:279
|
||||
#: admin/forms/alias.py:72
|
||||
msgid "Domain does not exist"
|
||||
msgstr "Domän existerar inte"
|
||||
|
||||
#: admin/forms/account.py:355
|
||||
msgid "Domain(s)"
|
||||
msgstr "Domän(er)"
|
||||
|
||||
#: admin/forms/account.py:357
|
||||
msgid "Domain(s) that user administrates"
|
||||
msgstr "Domän(er) användaren administrerar"
|
||||
|
||||
#: admin/forms/account.py:401 admin/forms/account.py:487
|
||||
#: admin/forms/domain.py:300 admin/forms/domain.py:370
|
||||
msgid "General"
|
||||
msgstr "Generellt"
|
||||
|
||||
#: admin/forms/account.py:406 admin/forms/account.py:493
|
||||
msgid "Mail"
|
||||
msgstr "Post"
|
||||
|
||||
#: admin/forms/account.py:409
|
||||
msgid "Permissions"
|
||||
msgstr "Rättigheter"
|
||||
|
||||
#: admin/forms/account.py:476
|
||||
msgid "Account updated"
|
||||
msgstr "Konto uppdaterat"
|
||||
|
||||
#: admin/forms/account.py:500
|
||||
msgid "New account"
|
||||
msgstr "Nytt konto"
|
||||
|
||||
#: admin/forms/account.py:512
|
||||
msgid "Account created"
|
||||
msgstr "Konto skapat"
|
||||
|
||||
#: admin/forms/alias.py:23
|
||||
msgid "Email address"
|
||||
msgstr "E-post adress"
|
||||
|
||||
#: admin/forms/alias.py:25
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The alias address (without the domain part). For a 'catch-all' address, "
|
||||
#| "just enter an * character."
|
||||
msgid ""
|
||||
"The alias address. To create a catchall alias, just enter the domain name "
|
||||
"(@domain.tld)."
|
||||
msgstr ""
|
||||
"Alias adress (utan domän delen). För en \"catch-all\"-adress, ange bara "
|
||||
"asterisk *."
|
||||
|
||||
#: admin/forms/alias.py:31
|
||||
msgid "Recipients"
|
||||
msgstr "Mottagare"
|
||||
|
||||
#: admin/forms/alias.py:33
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Mailbox(es) this alias will point to. Indicate only one address per "
|
||||
#| "input, press ENTER to add a new input."
|
||||
msgid ""
|
||||
"Addresses 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."
|
||||
|
||||
#: admin/forms/alias.py:75
|
||||
msgid "You don't have access to this domain"
|
||||
msgstr "Du har inte åtkomst till denna domän"
|
||||
|
||||
#: admin/forms/alias.py:85
|
||||
msgid "No recipient defined"
|
||||
msgstr "Ingen mottagare definierad"
|
||||
|
||||
#: admin/forms/domain.py:22 admin/models/domain.py:76
|
||||
#: admin/templates/admin/domain_statistics.html:49
|
||||
msgid "Domain"
|
||||
msgstr "Domän"
|
||||
|
||||
#: admin/forms/domain.py:32 admin/templates/admin/domain_statistics.html:26
|
||||
msgid "Type"
|
||||
msgstr "Typ"
|
||||
|
||||
#: admin/forms/domain.py:38
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:46
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:97 admin/forms/domain.py:108
|
||||
#: admin/forms/domain.py:116
|
||||
#, python-format
|
||||
msgid "A %s with this name already exists"
|
||||
msgstr "En %s med detta namn finns redan"
|
||||
|
||||
#: admin/forms/domain.py:108 admin/forms/domain.py:113
|
||||
msgid "domain"
|
||||
msgstr "domän"
|
||||
|
||||
#: admin/forms/domain.py:200
|
||||
msgid "Create a domain administrator"
|
||||
msgstr "Skapa en domän administratör"
|
||||
|
||||
#: admin/forms/domain.py:203
|
||||
msgid "Automatically create an administrator for this domain"
|
||||
msgstr "Skapa en domän administratör automatiskt för denna domän"
|
||||
|
||||
#: admin/forms/domain.py:208 admin/templates/admin/domains.html:25
|
||||
#: admin/templates/admin/editdomainform.html:13
|
||||
#: admin/templates/admin/identity_headers.html:2
|
||||
msgid "Name"
|
||||
msgstr "Namn"
|
||||
|
||||
#: admin/forms/domain.py:211
|
||||
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."
|
||||
|
||||
#: admin/forms/domain.py:218
|
||||
msgid "Create aliases"
|
||||
msgstr "Skapa alias."
|
||||
|
||||
#: admin/forms/domain.py:221
|
||||
msgid "Automatically create standard aliases for this domain"
|
||||
msgstr "Skapa automatiskt standard alias för den här domänen"
|
||||
|
||||
#: admin/forms/domain.py:240
|
||||
msgid "Invalid format"
|
||||
msgstr "Ogiltigt format"
|
||||
|
||||
#: admin/forms/domain.py:257
|
||||
#, python-format
|
||||
msgid "User '%s' already exists"
|
||||
msgstr "Användare '%s' finns redan"
|
||||
|
||||
#: admin/forms/domain.py:359
|
||||
msgid "Domain modified"
|
||||
msgstr "Domän ändrad"
|
||||
|
||||
#: admin/forms/domain.py:379
|
||||
msgid "Options"
|
||||
msgstr "Inställningar"
|
||||
|
||||
#: admin/forms/domain.py:387
|
||||
msgid "New domain"
|
||||
msgstr "Ny domän"
|
||||
|
||||
#: admin/forms/domain.py:405
|
||||
msgid "Domain created"
|
||||
msgstr "Domän skapad"
|
||||
|
||||
#: admin/forms/export.py:7
|
||||
msgid "File name"
|
||||
msgstr "Filnamn"
|
||||
|
||||
#: admin/forms/export.py:13 admin/forms/import_.py:13
|
||||
msgid "Separator"
|
||||
msgstr "Separator"
|
||||
|
||||
#: admin/forms/forward.py:14
|
||||
msgid "Recipient(s)"
|
||||
msgstr "Mottagare"
|
||||
|
||||
#: admin/forms/forward.py:18
|
||||
msgid "Indicate one or more recipients separated by a ','"
|
||||
msgstr "Ange en eller flera mottagare separerade med ett ','"
|
||||
|
||||
#: admin/forms/forward.py:21
|
||||
msgid "Keep local copies"
|
||||
msgstr "Behåll lokal kopia"
|
||||
|
||||
#: admin/forms/forward.py:24
|
||||
msgid "Forward messages and store copies into your local mailbox"
|
||||
msgstr "Vidarebefordra meddelande och spara kopia i din lokala brevlåda"
|
||||
|
||||
#: admin/forms/forward.py:42
|
||||
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."
|
||||
|
||||
#: admin/forms/import_.py:11
|
||||
msgid "Select a file"
|
||||
msgstr "Välj en fil"
|
||||
|
||||
#: admin/forms/import_.py:19
|
||||
msgid "Continue on error"
|
||||
msgstr "Fortsätt vid fel"
|
||||
|
||||
#: admin/forms/import_.py:20
|
||||
msgid "Don't treat duplicated objects as error"
|
||||
msgstr "Behandla inte dubletter som fel"
|
||||
|
||||
#: admin/forms/import_.py:38
|
||||
msgid "Crypt passwords"
|
||||
msgstr "Krypterade lösenord"
|
||||
|
||||
#: admin/forms/import_.py:40
|
||||
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"
|
||||
|
||||
#: admin/lib.py:30
|
||||
msgid "A mailbox is required"
|
||||
msgstr "En brevlåda krävs"
|
||||
|
||||
#: admin/lib.py:120
|
||||
#, fuzzy
|
||||
#| msgid "You can't delete your own domain"
|
||||
msgid "You are not allowed to import domains"
|
||||
msgstr "Du kan inte radera din egen domän"
|
||||
|
||||
#: admin/lib.py:129
|
||||
msgid "You are not allowed to import domain aliases."
|
||||
msgstr ""
|
||||
|
||||
#: admin/models/alias.py:26 admin/models/mailbox.py:77
|
||||
msgid "address"
|
||||
msgstr "adress"
|
||||
|
||||
#: admin/models/alias.py:28
|
||||
#, fuzzy
|
||||
#| msgid "The alias name"
|
||||
msgid "The alias address."
|
||||
msgstr "Alias namn"
|
||||
|
||||
#: admin/models/alias.py:33 admin/models/domain.py:37
|
||||
#: admin/models/domain_alias.py:24
|
||||
msgid "enabled"
|
||||
msgstr "aktiverad"
|
||||
|
||||
#: admin/models/alias.py:34 admin/models/domain_alias.py:25
|
||||
msgid "Check to activate this alias"
|
||||
msgstr "Markera för aktivera detta alias"
|
||||
|
||||
#: admin/models/alias.py:79
|
||||
msgid "distribution list"
|
||||
msgstr "distributionslista"
|
||||
|
||||
#: admin/models/alias.py:80
|
||||
msgid "forward"
|
||||
msgstr "vidarebefordra"
|
||||
|
||||
#: admin/models/alias.py:81
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: admin/models/alias.py:112
|
||||
#, fuzzy
|
||||
#| msgid "Invalid request"
|
||||
msgid "Invalid address"
|
||||
msgstr "Ogiltig förfrågan"
|
||||
|
||||
#: admin/models/alias.py:133
|
||||
#, fuzzy
|
||||
#| msgid "Local recipient %s not found"
|
||||
msgid "Local recipient {}@{} not found"
|
||||
msgstr "Lokal mottagare %s kunde inte hittas"
|
||||
|
||||
#: admin/models/alias.py:162
|
||||
#, python-format
|
||||
msgid "Invalid line: %s"
|
||||
msgstr "Ogiltig rad: %s"
|
||||
|
||||
#: admin/models/alias.py:168
|
||||
#, python-format
|
||||
msgid "Domain '%s' does not exist"
|
||||
msgstr "Domänen '%s' existerar inte"
|
||||
|
||||
#: admin/models/domain.py:33 admin/models/domain_alias.py:17
|
||||
msgid "name"
|
||||
msgstr "namn"
|
||||
|
||||
#: admin/models/domain.py:34
|
||||
msgid "The domain name"
|
||||
msgstr "Domännamnet"
|
||||
|
||||
#: admin/models/domain.py:38
|
||||
msgid "Check to activate this domain"
|
||||
msgstr "Markera för att aktivera denna domän"
|
||||
|
||||
#: admin/models/domain.py:160 admin/models/domain_alias.py:47
|
||||
msgid "Invalid line"
|
||||
msgstr "Ogiltig rad"
|
||||
|
||||
#: admin/models/domain.py:168
|
||||
#, python-format
|
||||
msgid "Invalid quota value for domain '%s'"
|
||||
msgstr "Ogiltig kvota värde för domänen '%s'"
|
||||
|
||||
#: admin/models/domain_alias.py:18
|
||||
msgid "The alias name"
|
||||
msgstr "Alias namn"
|
||||
|
||||
#: admin/models/domain_alias.py:20
|
||||
msgid "target"
|
||||
msgstr "mål"
|
||||
|
||||
#: admin/models/domain_alias.py:21
|
||||
msgid "The domain this alias points to"
|
||||
msgstr "Domän dit detta alias pekar mot"
|
||||
|
||||
#: admin/models/domain_alias.py:56
|
||||
#, python-format
|
||||
msgid "Unknown domain %s"
|
||||
msgstr "Okänt kommando %s"
|
||||
|
||||
#: admin/models/mailbox.py:79
|
||||
msgid "Mailbox address (without the @domain.tld part)"
|
||||
msgstr "Brevlåde adress (utan @domain.tld)"
|
||||
|
||||
#: admin/models/mailbox.py:144
|
||||
#, python-format
|
||||
msgid "Failed to retrieve mailbox location (%s)"
|
||||
msgstr "Kunde inte hitta brevlådans sökväg (%s)"
|
||||
|
||||
#: admin/models/mailbox.py:233
|
||||
#, python-format
|
||||
msgid "Quota is greater than the allowed domain's limit (%dM)"
|
||||
msgstr "Kvotan är större än domänens gräns (%dM)"
|
||||
|
||||
#: admin/models/mailbox.py:239
|
||||
msgid "A quota is required"
|
||||
msgstr "En kvota krävs"
|
||||
|
||||
#: admin/templates/admin/account_general_form.html:11
|
||||
#: admin/templates/admin/aliasform.html:8
|
||||
msgid "Domain is disabled"
|
||||
msgstr "Domänen är inaktiverad"
|
||||
|
||||
#: admin/templates/admin/domain_general_form.html:4
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
#: admin/templates/admin/newdomainform.html:3
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
#: admin/templatetags/admin_tags.py:45
|
||||
msgid "Statistics"
|
||||
msgstr "Statistik"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:15
|
||||
msgid "Domains and identities"
|
||||
msgstr "Domäner och konton"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:22
|
||||
msgid "Global counters"
|
||||
msgstr "Globala räknare"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:27
|
||||
msgid "Quantity"
|
||||
msgstr "Mängd"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:33
|
||||
#: admin/templates/admin/editdomainform.html:24
|
||||
msgid "Domain aliases"
|
||||
msgstr "Domän alias"
|
||||
|
||||
#: admin/templates/admin/domain_statistics.html:45
|
||||
msgid "Per-domain counters"
|
||||
msgstr "Per domän räknare"
|
||||
|
||||
#: admin/templates/admin/domains.html:27
|
||||
#: admin/templates/admin/identity_headers.html:4
|
||||
msgid "Tags"
|
||||
msgstr "Tagg"
|
||||
|
||||
#: admin/templates/admin/domains.html:28
|
||||
#: admin/templates/admin/identity_headers.html:5
|
||||
msgid "Actions"
|
||||
msgstr "Åtgärder"
|
||||
|
||||
#: admin/templates/admin/domains_table.html:4
|
||||
msgid "disabled"
|
||||
msgstr "inaktiverad"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:4
|
||||
msgid "Administrators"
|
||||
msgstr "Administratörer"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:7
|
||||
msgid "Miscellaneous"
|
||||
msgstr "Övrigt"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:19
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Ingen domän administratör definierad"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:22
|
||||
msgid "Creation date"
|
||||
msgstr "Skapelsedatum"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:23
|
||||
msgid "Last modification date"
|
||||
msgstr "Senast ändrad"
|
||||
|
||||
#: admin/templates/admin/editdomainform.html:26
|
||||
msgid "Mailbox aliases"
|
||||
msgstr "Brevlåde alias"
|
||||
|
||||
#: admin/templates/admin/forward.html:2
|
||||
msgid "Automatically forward emails to another address"
|
||||
msgstr "Vidarebefordra automatiskt e-post till en annan adress"
|
||||
|
||||
#: admin/templates/admin/forward.html:9 admin/views/alias.py:113
|
||||
msgid "Update"
|
||||
msgstr "Uppdatera"
|
||||
|
||||
#: admin/templates/admin/identity_headers.html:3
|
||||
msgid "Fullname/Recipient"
|
||||
msgstr "Fullständigt namn/Mottagare"
|
||||
|
||||
#: admin/templates/admin/importform.html:6
|
||||
msgid "Help"
|
||||
msgstr "Hjälp"
|
||||
|
||||
#: admin/templates/admin/importform.html:13
|
||||
msgid "Importing..."
|
||||
msgstr "Importerar..."
|
||||
|
||||
#: admin/templates/admin/mailboxes_raw.html:3
|
||||
msgid "Choose a value"
|
||||
msgstr "Välj ett värde"
|
||||
|
||||
#: admin/templates/admin/mailform.html:3
|
||||
msgid "Use domain default value"
|
||||
msgstr "Använd domänens standardvärde"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:2
|
||||
msgid "Address"
|
||||
msgstr "Adress"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:3
|
||||
msgid "Value"
|
||||
msgstr "Värde"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:4
|
||||
msgid "Limit"
|
||||
msgstr "Gräns"
|
||||
|
||||
#: admin/templates/admin/quota_headers.html:5
|
||||
#, python-format
|
||||
msgid "Usage (%%)"
|
||||
msgstr "Användning (%%)"
|
||||
|
||||
#: admin/templates/admin/searchform.html:6
|
||||
msgid "Search"
|
||||
msgstr "Sök"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_m"
|
||||
msgstr "enabled_m"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:19
|
||||
msgid "enabled_f"
|
||||
msgstr "enabled_f"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:40
|
||||
msgid "List domains"
|
||||
msgstr "Lista domäner"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:53
|
||||
msgid "Add domain"
|
||||
msgstr "Lägg till domän"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:62 admin/templatetags/admin_tags.py:126
|
||||
#: admin/views/import_.py:99 admin/views/import_.py:133
|
||||
msgid "Import"
|
||||
msgstr "Importera"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:68 admin/templatetags/admin_tags.py:132
|
||||
#: admin/views/export.py:41 admin/views/export.py:69
|
||||
msgid "Export"
|
||||
msgstr "Exportera"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:92
|
||||
msgid "List identities"
|
||||
msgstr "Lista konton"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:97
|
||||
msgid "List quotas"
|
||||
msgstr "Lista kvoter"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:102
|
||||
msgid "Add account"
|
||||
msgstr "Lägg till konto"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:108
|
||||
msgid "Add alias"
|
||||
msgstr "Lägg till alias"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:114
|
||||
msgid "Add forward"
|
||||
msgstr "Lägg till vidarebefodring"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:120
|
||||
msgid "Add distribution list"
|
||||
msgstr "Lägg till distributionslista"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:152
|
||||
msgid "View the domain's identities"
|
||||
msgstr "Visa domänens konton"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:159 admin/templatetags/admin_tags.py:182
|
||||
#: admin/templatetags/admin_tags.py:190
|
||||
#, python-format
|
||||
msgid "Delete %s?"
|
||||
msgstr "Radera %s?"
|
||||
|
||||
#: admin/templatetags/admin_tags.py:267
|
||||
msgid "Remove this permission"
|
||||
msgstr "Radera detta tillstånd"
|
||||
|
||||
#: admin/views/alias.py:29
|
||||
msgid "Alias with this name already exists"
|
||||
msgstr "Alias med detta namn existerar redan"
|
||||
|
||||
#: admin/views/alias.py:53
|
||||
msgid "Create"
|
||||
msgstr "Skapa"
|
||||
|
||||
#: admin/views/alias.py:65
|
||||
msgid "New distribution list"
|
||||
msgstr "Ny distributionslista"
|
||||
|
||||
#: admin/views/alias.py:67
|
||||
msgid "Distribution list created"
|
||||
msgstr "Distributionslista skapad"
|
||||
|
||||
#: admin/views/alias.py:76
|
||||
msgid "New alias"
|
||||
msgstr "Nytt alias"
|
||||
|
||||
#: admin/views/alias.py:77
|
||||
msgid "Alias created"
|
||||
msgstr "Alias skapat"
|
||||
|
||||
#: admin/views/alias.py:86
|
||||
msgid "New forward"
|
||||
msgstr "Ny vidarebefodring"
|
||||
|
||||
#: admin/views/alias.py:87
|
||||
msgid "Forward created"
|
||||
msgstr "Vidarebefodring skapad"
|
||||
|
||||
#: admin/views/alias.py:101
|
||||
msgid "Distribution list modified"
|
||||
msgstr "Distributionslista ändrad"
|
||||
|
||||
#: admin/views/alias.py:103
|
||||
msgid "Forward modified"
|
||||
msgstr "Vidarebefodring ändrad"
|
||||
|
||||
#: admin/views/alias.py:105
|
||||
msgid "Alias modified"
|
||||
msgstr "Alias ändrat"
|
||||
|
||||
#: admin/views/domain.py:132
|
||||
msgid "You can't delete your own domain"
|
||||
msgstr "Du kan inte radera din egen domän"
|
||||
|
||||
#: admin/views/domain.py:135
|
||||
msgid "Domain deleted"
|
||||
msgid_plural "Domains deleted"
|
||||
msgstr[0] "Domän raderad"
|
||||
msgstr[1] "Domäner raderade"
|
||||
|
||||
#: admin/views/export.py:40
|
||||
msgid "Export identities"
|
||||
msgstr "Exportera konton"
|
||||
|
||||
#: admin/views/export.py:68
|
||||
msgid "Export domains"
|
||||
msgstr "Exportera domäner"
|
||||
|
||||
#: admin/views/identity.py:108 admin/views/identity.py:200
|
||||
#: admin/views/identity.py:205
|
||||
msgid "Invalid request"
|
||||
msgstr "Ogiltig förfrågan"
|
||||
|
||||
#: admin/views/identity.py:190
|
||||
msgid "Account deleted"
|
||||
msgid_plural "Accounts deleted"
|
||||
msgstr[0] "Konto raderat"
|
||||
msgstr[1] "Konton raderade"
|
||||
|
||||
#: admin/views/import_.py:64
|
||||
#, python-format
|
||||
msgid "Object already exists: %s"
|
||||
msgstr "Objektet existerar redan: %s"
|
||||
|
||||
#: admin/views/import_.py:68
|
||||
#, python-format
|
||||
msgid "%d objects imported successfully"
|
||||
msgstr "%d objekt importerade"
|
||||
|
||||
#: admin/views/import_.py:86
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
" <li><em>domain; name; quota; enabled</em></li>\n"
|
||||
" <li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
" %s\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Tillhandahåll en CSV fil där raderna har följande format:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>domain; name; quota; enabled</em></li>\n"
|
||||
"<li><em>domainalias; name; targeted domain; enabled</em></li>\n"
|
||||
"%s\n"
|
||||
"</ul>\n"
|
||||
"<p>det första elementet i varje rad är obligatoriskt och måste vara lika med "
|
||||
"en av de tidigare värdena.</ p>\n"
|
||||
"<p>Du kan använda ett annat tecken som separator.</ p>\n"
|
||||
|
||||
#: admin/views/import_.py:98
|
||||
msgid "Import domains"
|
||||
msgstr "Importera domäner"
|
||||
|
||||
#: admin/views/import_.py:120
|
||||
msgid ""
|
||||
"Provide a CSV file where lines respect one of the following formats:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>The first element of each line is mandatory and must be equal to one of "
|
||||
"the previous values.</p>\n"
|
||||
"\n"
|
||||
"<p>You can use a different character as separator.</p>\n"
|
||||
msgstr ""
|
||||
"Tillhandahåll en CSV-fil där raderna har följande format:\n"
|
||||
"<ul>\n"
|
||||
"<li><em>account; loginname; password; first name; last name; enabled; group; "
|
||||
"address; quota; [, domain, ...]</em></li>\n"
|
||||
"<li><em>alias; address; enabled; internal recipient</em></li>\n"
|
||||
"<li><em>forward; address; enabled; external recipient</em></li>\n"
|
||||
"<li><em>dlist; address; enabled; recipient; recipient; ...</em></li>\n"
|
||||
"</ul>\n"
|
||||
"<p>Det första elementet i varje rad är obligatorisk och måste vara lika med "
|
||||
"en av de tidigare värdena.</p>\n"
|
||||
"\n"
|
||||
"<p>Du kan använda ett annat tecken separator.</p>\n"
|
||||
|
||||
#: admin/views/import_.py:132
|
||||
msgid "Import identities"
|
||||
msgstr "Importera konton"
|
||||
|
||||
#: admin/views/user.py:34
|
||||
msgid "Forward updated"
|
||||
msgstr "Vidarebefordring uppdaterad"
|
||||
@@ -0,0 +1,57 @@
|
||||
# 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 <olle@dalnix.se>, 2013
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2013,2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-11-09 08:20+0100\n"
|
||||
"PO-Revision-Date: 2015-01-13 15:21+0000\n"
|
||||
"Last-Translator: Olle Gustafsson <olle@dalnix.se>\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"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/admin/js/admin.js:126
|
||||
msgid "No more domain to show"
|
||||
msgstr "Inga fler domäner att visa"
|
||||
|
||||
#: static/admin/js/admin.js:145
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Radera inte domän katalog"
|
||||
|
||||
#: static/admin/js/admin.js:147
|
||||
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."
|
||||
|
||||
#: static/admin/js/admin.js:148
|
||||
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."
|
||||
|
||||
#: static/admin/js/admin.js:231
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Ingen domänadministratör definierad"
|
||||
|
||||
#: static/admin/js/admin.js:286 static/admin/js/admin.js.c:354
|
||||
msgid "No more identity to show"
|
||||
msgstr "Inga fler konton att visa"
|
||||
|
||||
#: static/admin/js/admin.js:328
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Radera inte brevlådans katalog"
|
||||
|
||||
#: static/admin/js/admin.js:357
|
||||
msgid "No more quota to show"
|
||||
msgstr "Ingen mer kvota att visa"
|
||||
@@ -0,0 +1,53 @@
|
||||
import os.path
|
||||
import sys
|
||||
import csv
|
||||
from progressbar import ProgressBar, Percentage, Bar, ETA
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import Conflict
|
||||
|
||||
from ... import lib
|
||||
|
||||
|
||||
def import_csv(filename, options):
|
||||
"""Import objects from a CSV file."""
|
||||
superadmin = User.objects.filter(is_superuser=True).first()
|
||||
if not os.path.exists(filename):
|
||||
print('File not found')
|
||||
sys.exit(1)
|
||||
|
||||
num_lines = sum(1 for line in open(filename))
|
||||
pbar = ProgressBar(
|
||||
widgets=[Percentage(), Bar(), ETA()], maxval=num_lines
|
||||
).start()
|
||||
with open(filename, 'r') as f:
|
||||
reader = csv.reader(f, delimiter=';')
|
||||
i = 0
|
||||
for row in reader:
|
||||
i += 1
|
||||
pbar.update(i)
|
||||
if not row:
|
||||
continue
|
||||
|
||||
try:
|
||||
fct = getattr(lib, "import_%s" % row[0].strip())
|
||||
except AttributeError:
|
||||
fct = events.raiseQueryEvent(
|
||||
'ImportObject', row[0].strip())
|
||||
if not fct:
|
||||
continue
|
||||
fct = fct[0]
|
||||
|
||||
try:
|
||||
fct(superadmin, row, options)
|
||||
except Conflict:
|
||||
if options['continue_if_exists']:
|
||||
continue
|
||||
|
||||
raise Conflict(
|
||||
"Object already exists: %s"
|
||||
% options['sepchar'].join(row[:2])
|
||||
)
|
||||
|
||||
pbar.finish()
|
||||
@@ -0,0 +1,28 @@
|
||||
import sys
|
||||
import csv
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.core.management.commands import CloseConnectionMixin
|
||||
from ...models import Domain
|
||||
|
||||
|
||||
class Command(BaseCommand, CloseConnectionMixin):
|
||||
help = 'Export domains and domain aliases to a csv'
|
||||
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option(
|
||||
'--sepchar', action='store_true', dest='sepchar', default=';'
|
||||
),
|
||||
)
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
exts_pool.load_all()
|
||||
load_core_settings()
|
||||
|
||||
csvwriter = csv.writer(sys.stdout, delimiter=kwargs['sepchar'])
|
||||
for dom in Domain.objects.all():
|
||||
dom.to_csv(csvwriter)
|
||||
@@ -0,0 +1,32 @@
|
||||
import sys
|
||||
import csv
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.models import User
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.core.management.commands import CloseConnectionMixin
|
||||
from ...models import Alias
|
||||
|
||||
|
||||
class Command(BaseCommand, CloseConnectionMixin):
|
||||
help = 'Export identities (mailbox and aliases) to a csv'
|
||||
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option(
|
||||
'--sepchar', action='store_true', dest='sepchar', default=';'
|
||||
),
|
||||
)
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
exts_pool.load_all()
|
||||
load_core_settings()
|
||||
|
||||
csvwriter = csv.writer(sys.stdout, delimiter=kwargs['sepchar'])
|
||||
for u in User.objects.all():
|
||||
u.to_csv(csvwriter)
|
||||
|
||||
for a in Alias.objects.prefetch_related('mboxes', 'aliases'):
|
||||
a.to_csv(csvwriter)
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
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 ...models import MailboxOperation
|
||||
from ...modo_extension import AdminConsole
|
||||
|
||||
|
||||
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):
|
||||
AdminConsole().load()
|
||||
if parameters.get_admin("HANDLE_MAILBOXES") == 'no':
|
||||
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'])
|
||||
@@ -0,0 +1,32 @@
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.core.management.commands import CloseConnectionMixin
|
||||
|
||||
from ._import import import_csv
|
||||
|
||||
|
||||
class Command(BaseCommand, CloseConnectionMixin):
|
||||
args = 'csvfile'
|
||||
help = 'Import domains and domain aliases from a csv file'
|
||||
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option(
|
||||
'--sepchar', action='store_true', dest='sepchar', default=';'
|
||||
),
|
||||
make_option(
|
||||
'--continue-if-exists', action='store_true',
|
||||
dest='continue_if_exists', default=True
|
||||
)
|
||||
)
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
exts_pool.load_all()
|
||||
load_core_settings()
|
||||
|
||||
for filename in args:
|
||||
import_csv(filename, kwargs)
|
||||
@@ -0,0 +1,35 @@
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from modoboa.core import load_core_settings
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.core.management.commands import CloseConnectionMixin
|
||||
|
||||
from ._import import import_csv
|
||||
|
||||
|
||||
class Command(BaseCommand, CloseConnectionMixin):
|
||||
args = 'csvfile'
|
||||
help = 'Import identities from a csv file'
|
||||
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option(
|
||||
'--sepchar', action='store_true', dest='sepchar', default=';'
|
||||
),
|
||||
make_option(
|
||||
'--continue-if-exists', action='store_true',
|
||||
dest='continue_if_exists', default=True
|
||||
),
|
||||
make_option(
|
||||
'--crypt-password', action='store_true', dest='crypt_password',
|
||||
default=False
|
||||
)
|
||||
)
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
exts_pool.load_all()
|
||||
load_core_settings()
|
||||
|
||||
for filename in args:
|
||||
import_csv(filename, kwargs)
|
||||
@@ -0,0 +1,178 @@
|
||||
# -*- 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.', max_length=254, verbose_name='address')),
|
||||
('enabled', models.BooleanField(default=True, help_text='Check to activate this alias', verbose_name='enabled')),
|
||||
('internal', models.BooleanField(default=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['address'],
|
||||
'permissions': (('view_aliases', 'View aliases'),),
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AliasRecipient',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('address', models.EmailField(max_length=75)),
|
||||
('alias', models.ForeignKey(to='admin.Alias')),
|
||||
('r_alias', models.ForeignKey(related_name='alias_recipient_aliases', blank=True, to='admin.Alias', null=True)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'modoboa_admin_aliasrecipient',
|
||||
},
|
||||
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')),
|
||||
('type', models.CharField(default=b'domain', max_length=20)),
|
||||
],
|
||||
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.OneToOneField(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='aliasrecipient',
|
||||
name='r_mailbox',
|
||||
field=models.ForeignKey(blank=True, to='admin.Mailbox', null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='aliasrecipient',
|
||||
unique_together=set([('alias', 'r_alias'), ('alias', 'r_mailbox')]),
|
||||
),
|
||||
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', null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='alias',
|
||||
unique_together=set([('address', 'internal')]),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
def rename_and_clean(apps, schema_editor):
|
||||
"""Rename old content types if necessary, remove permissions."""
|
||||
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||
for ct in ContentType.objects.filter(app_label="admin"):
|
||||
try:
|
||||
old_ct = ContentType.objects.get(
|
||||
app_label="modoboa_admin", model=ct.model)
|
||||
except ContentType.DoesNotExist:
|
||||
continue
|
||||
old_ct.app_label = "admin"
|
||||
ct.delete()
|
||||
old_ct.save()
|
||||
|
||||
# Remove DomainAlias permissions from DomainAdmins group
|
||||
Group = apps.get_model("auth", "Group")
|
||||
try:
|
||||
group = Group.objects.get(name="DomainAdmins")
|
||||
except Group.DoesNotExist:
|
||||
return
|
||||
Permission = apps.get_model("auth", "Permission")
|
||||
ct = ContentType.objects.get(app_label="admin", model="domainalias")
|
||||
for permission in Permission.objects.filter(content_type=ct):
|
||||
group.permissions.remove(permission)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('admin', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_and_clean),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
from .base import AdminObject
|
||||
from .domain import Domain
|
||||
from .domain_alias import DomainAlias
|
||||
from .mailbox import Mailbox, Quota, MailboxOperation
|
||||
from .alias import Alias, AliasRecipient
|
||||
|
||||
__all__ = [
|
||||
'Domain', 'DomainAlias', 'Mailbox', 'Quota', 'Alias',
|
||||
'MailboxOperation', 'AdminObject', 'AliasRecipient'
|
||||
]
|
||||
@@ -0,0 +1,214 @@
|
||||
"""Models related to aliases management."""
|
||||
|
||||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible, smart_text
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
import reversion
|
||||
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
from modoboa.lib.exceptions import (
|
||||
PermDeniedException, BadRequest, Conflict, NotFound
|
||||
)
|
||||
|
||||
from .base import AdminObject
|
||||
from .domain import Domain
|
||||
from .mailbox import Mailbox
|
||||
from .. import signals
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Alias(AdminObject):
|
||||
|
||||
"""Mailbox alias."""
|
||||
|
||||
address = models.CharField(
|
||||
ugettext_lazy('address'), max_length=254,
|
||||
help_text=ugettext_lazy(
|
||||
"The alias address."
|
||||
)
|
||||
)
|
||||
domain = models.ForeignKey(Domain, null=True)
|
||||
enabled = models.BooleanField(
|
||||
ugettext_lazy('enabled'),
|
||||
help_text=ugettext_lazy("Check to activate this alias"),
|
||||
default=True
|
||||
)
|
||||
internal = models.BooleanField(default=False)
|
||||
_objectname = 'MailboxAlias'
|
||||
|
||||
class Meta:
|
||||
permissions = (
|
||||
("view_aliases", "View aliases"),
|
||||
)
|
||||
ordering = ["address"]
|
||||
unique_together = (("address", "internal"), )
|
||||
app_label = "admin"
|
||||
|
||||
def __str__(self):
|
||||
return smart_text(self.address)
|
||||
|
||||
@property
|
||||
def identity(self):
|
||||
return self.address
|
||||
|
||||
@property
|
||||
def name_or_rcpt(self):
|
||||
rcpts_count = self.recipients_count
|
||||
if not rcpts_count:
|
||||
return "---"
|
||||
rcpts = self.recipients
|
||||
if rcpts_count > 1:
|
||||
return "%s, ..." % rcpts[0]
|
||||
return rcpts[0]
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
cpt = self.recipients_count
|
||||
if cpt > 1:
|
||||
return "dlist"
|
||||
qset = self.aliasrecipient_set.filter(
|
||||
r_mailbox__isnull=True, r_alias__isnull=True)
|
||||
if qset.exists():
|
||||
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 set_recipients(self, address_list):
|
||||
"""Set recipients for this alias. Special recipients:
|
||||
|
||||
* local mailbox + extension: r_mailbox will be set to local mailbox
|
||||
* alias address == recipient address: valid only to keep local copies
|
||||
(when a forward is defined) and to create exceptions when a catchall
|
||||
is defined on the associated domain
|
||||
|
||||
"""
|
||||
to_create = []
|
||||
for address in set(address_list):
|
||||
if not address:
|
||||
continue
|
||||
if self.aliasrecipient_set.filter(address=address).exists():
|
||||
continue
|
||||
local_part, domname, extension = (
|
||||
split_mailbox(address, return_extension=True))
|
||||
if domname is None:
|
||||
raise BadRequest(
|
||||
u"%s %s" % (_("Invalid address"), address)
|
||||
)
|
||||
domain = Domain.objects.filter(name=domname).first()
|
||||
kwargs = {"address": address, "alias": self}
|
||||
if (
|
||||
(domain is not None) and
|
||||
(
|
||||
any(
|
||||
r[1] for r in signals.use_external_recipients.send(
|
||||
self, recipients=address)
|
||||
) is False
|
||||
)
|
||||
):
|
||||
rcpt = Mailbox.objects.filter(
|
||||
domain=domain, address=local_part).first()
|
||||
if rcpt is None:
|
||||
rcpt = Alias.objects.filter(
|
||||
address='%s@%s' % (local_part, domname)
|
||||
).first()
|
||||
if rcpt is None:
|
||||
raise NotFound(
|
||||
_("Local recipient {}@{} not found")
|
||||
.format(local_part, domname)
|
||||
)
|
||||
if rcpt.address == self.address:
|
||||
raise Conflict
|
||||
kwargs["r_alias"] = rcpt
|
||||
else:
|
||||
kwargs["r_mailbox"] = rcpt
|
||||
to_create.append(AliasRecipient(**kwargs))
|
||||
AliasRecipient.objects.bulk_create(to_create)
|
||||
# Remove old recipients
|
||||
self.aliasrecipient_set.exclude(
|
||||
address__in=address_list).delete()
|
||||
|
||||
@property
|
||||
def recipients(self):
|
||||
"""Return the recipient list."""
|
||||
return self.aliasrecipient_set.values_list("address", flat=True)
|
||||
|
||||
@property
|
||||
def recipients_count(self):
|
||||
"""Return the number of recipients of this alias."""
|
||||
return self.aliasrecipient_set.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))
|
||||
address = row[1].strip()
|
||||
localpart, domname = split_mailbox(address)
|
||||
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
|
||||
if Alias.objects.filter(address=address).exists():
|
||||
raise Conflict
|
||||
self.address = address
|
||||
self.domain = domain
|
||||
self.enabled = (row[2].strip() in ["True", "1", "yes", "y"])
|
||||
self.save()
|
||||
self.set_recipients([raddress.strip() for raddress in row[3:]])
|
||||
self.post_create(user)
|
||||
|
||||
def to_csv(self, csvwriter):
|
||||
row = [self.type, self.address.encode("utf-8"), self.enabled]
|
||||
row += self.recipients
|
||||
csvwriter.writerow(row)
|
||||
|
||||
reversion.register(Alias)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class AliasRecipient(models.Model):
|
||||
|
||||
"""An alias recipient."""
|
||||
|
||||
address = models.EmailField()
|
||||
alias = models.ForeignKey(Alias)
|
||||
|
||||
# if recipient is a local mailbox
|
||||
r_mailbox = models.ForeignKey(Mailbox, blank=True, null=True)
|
||||
# if recipient is a local alias
|
||||
r_alias = models.ForeignKey(
|
||||
Alias, related_name="alias_recipient_aliases", blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
app_label = "admin"
|
||||
db_table = "modoboa_admin_aliasrecipient"
|
||||
unique_together = [
|
||||
("alias", "r_mailbox"),
|
||||
("alias", "r_alias")
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
"""Return alias and recipient."""
|
||||
return smart_text(
|
||||
"{} -> {}".format(self.alias.address, self.alias)
|
||||
)
|
||||
@@ -0,0 +1,82 @@
|
||||
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()
|
||||
@@ -0,0 +1,186 @@
|
||||
"""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)
|
||||
type = models.CharField(default="domain", max_length=20)
|
||||
|
||||
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.filter(internal=False).count())
|
||||
|
||||
@property
|
||||
def tags(self):
|
||||
if self.type == "domain":
|
||||
return [{"name": "domain", "label": _("Domain"), "type": "dom"}]
|
||||
return events.raiseQueryEvent("GetTagsForDomain", self)
|
||||
|
||||
@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()
|
||||
if Domain.objects.filter(name=self.name).exists():
|
||||
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)
|
||||
@@ -0,0 +1,68 @@
|
||||
"""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]:
|
||||
if model.objects.filter(name=self.name).exists():
|
||||
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)
|
||||
@@ -0,0 +1,320 @@
|
||||
"""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.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
|
||||
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.OneToOneField(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.recipientalias_set.select_related("alias")
|
||||
.filter(alias__internal=False).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 = []
|
||||
qset = (
|
||||
self.aliasrecipient_set.select_related("alias")
|
||||
.filter(alias__internal=False)
|
||||
)
|
||||
for alr in qset:
|
||||
aliases += [alr.alias.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)
|
||||
conditions = (
|
||||
creator.is_superuser,
|
||||
not self.user.has_perm("admin.add_domain")
|
||||
)
|
||||
if all(conditions):
|
||||
# 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
|
||||
|
||||
"""
|
||||
Quota.objects.filter(username=self.full_address).delete()
|
||||
if not keepdir:
|
||||
self.delete_dir()
|
||||
super(Mailbox, self).delete()
|
||||
|
||||
reversion.register(Mailbox)
|
||||
|
||||
|
||||
class MailboxOperation(models.Model):
|
||||
|
||||
"""An operation on a mailbox."""
|
||||
|
||||
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
|
||||
@@ -0,0 +1,143 @@
|
||||
"""Map file definitions for postfix."""
|
||||
|
||||
from modoboa.core.commands.postfix_maps import registry
|
||||
|
||||
|
||||
class DomainsMap(object):
|
||||
|
||||
"""Map to list all domains."""
|
||||
|
||||
filename = 'sql-domains.cf'
|
||||
mysql = (
|
||||
"SELECT name FROM admin_domain "
|
||||
"WHERE name='%s' AND type='domain' AND enabled=1"
|
||||
)
|
||||
postgres = (
|
||||
"SELECT name FROM admin_domain "
|
||||
"WHERE name='%s' AND type='domain' AND enabled"
|
||||
)
|
||||
sqlite = (
|
||||
"SELECT name FROM admin_domain "
|
||||
"WHERE name='%s' AND type='domain' AND enabled=1"
|
||||
)
|
||||
|
||||
|
||||
class DomainsAliasesMap(object):
|
||||
|
||||
"""Map to list all domain aliases."""
|
||||
|
||||
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(object):
|
||||
|
||||
"""A map to list all mailbox aliases."""
|
||||
|
||||
filename = 'sql-aliases.cf'
|
||||
mysql = (
|
||||
"SELECT alr.address FROM admin_aliasrecipient AS alr "
|
||||
"INNER JOIN admin_alias AS al ON alr.alias_id=al.id "
|
||||
"WHERE al.enabled=1 AND al.address='%s'"
|
||||
)
|
||||
postgres = (
|
||||
"SELECT alr.address FROM admin_aliasrecipient AS alr "
|
||||
"INNER JOIN admin_alias AS al ON alr.alias_id=al.id "
|
||||
"WHERE al.enabled AND al.address='%s'"
|
||||
)
|
||||
sqlite = (
|
||||
"SELECT alr.address FROM admin_aliasrecipient AS alr "
|
||||
"INNER JOIN admin_alias AS al ON alr.alias_id=al.id "
|
||||
"WHERE al.enabled=1 AND al.address='%s'"
|
||||
)
|
||||
|
||||
|
||||
class MaintainMap(object):
|
||||
|
||||
"""Map files to list non available mailboxes."""
|
||||
|
||||
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 SenderLoginMailboxMap(object):
|
||||
|
||||
"""Map file to list authorized sender addresses (from mailboxes)."""
|
||||
|
||||
filename = "sql-sender-login-mailboxes.cf"
|
||||
mysql = (
|
||||
"SELECT email FROM core_user WHERE email='%s' AND is_active=1 "
|
||||
)
|
||||
postgres = (
|
||||
"SELECT email FROM core_user WHERE email='%s' AND is_active"
|
||||
)
|
||||
sqlite = (
|
||||
"SELECT email FROM core_user WHERE email='%s' AND is_active=1"
|
||||
)
|
||||
|
||||
|
||||
class SenderLoginAliasMap(object):
|
||||
|
||||
"""Map file to list authorized sender addresses (from aliases)."""
|
||||
|
||||
filename = "sql-sender-login-aliases.cf"
|
||||
mysql = (
|
||||
"SELECT concat(mb.address, '@', dom.name) FROM admin_mailbox mb "
|
||||
"INNER JOIN admin_aliasrecipient alr ON alr.r_mailbox_id=mb.id"
|
||||
" INNER JOIN admin_domain dom ON dom.id=mb.domain_id"
|
||||
" INNER JOIN admin_alias al ON alr.alias_id=al.id "
|
||||
"WHERE al.enabled=1 AND al.address='%s'"
|
||||
)
|
||||
postgres = (
|
||||
"SELECT mb.address || '@' || dom.name FROM admin_mailbox mb "
|
||||
"INNER JOIN admin_aliasrecipient alr ON alr.r_mailbox_id=mb.id"
|
||||
" INNER JOIN admin_domain dom ON dom.id=mb.domain_id"
|
||||
" INNER JOIN admin_alias al ON alr.alias_id=al.id "
|
||||
"WHERE al.enabled AND al.address='%s'"
|
||||
)
|
||||
sqlite = (
|
||||
"SELECT mb.address || '@' || dom.name FROM admin_mailbox mb "
|
||||
"INNER JOIN admin_aliasrecipient alr ON alr.r_mailbox_id=mb.id"
|
||||
" INNER JOIN admin_domain dom ON dom.id=mb.domain_id"
|
||||
" INNER JOIN admin_alias al ON alr.alias_id=al.id "
|
||||
"WHERE al.enabled=1 AND al.address='%s'"
|
||||
)
|
||||
|
||||
registry.add_files([
|
||||
DomainsMap, DomainsAliasesMap, AliasesMap, MaintainMap,
|
||||
SenderLoginAliasMap, SenderLoginMailboxMap
|
||||
])
|
||||
@@ -0,0 +1,7 @@
|
||||
"""Modoboa admin signals."""
|
||||
|
||||
import django.dispatch
|
||||
|
||||
use_external_recipients = django.dispatch.Signal(providing_args=['recipients'])
|
||||
extra_domain_actions = django.dispatch.Signal(
|
||||
providing_args=["user", "domain"])
|
||||
@@ -0,0 +1,33 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
#settings_content .form-horizontal .control-label {
|
||||
margin-left: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#settings_content > .form-horizontal .controls {
|
||||
margin-left: 240px;
|
||||
}
|
||||
@@ -0,0 +1,573 @@
|
||||
/**
|
||||
* 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 === "yes") ?
|
||||
{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('<div class="alert alert-info">'
|
||||
+ gettext("No domain administrator defined") + "</div>");
|
||||
}
|
||||
}
|
||||
}]);
|
||||
});
|
||||
},
|
||||
|
||||
newdomain_cb: function() {
|
||||
this.generalform_init();
|
||||
this.optionsform_init();
|
||||
$("#wizard").cwizard({
|
||||
formid: "domform",
|
||||
transition_callbacks: {
|
||||
"options": this.optionsform_prefill
|
||||
},
|
||||
error_callbacks: {
|
||||
"options": $.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(group) {
|
||||
$("#id_email").removeClass("disabled")
|
||||
.attr("readonly", null)
|
||||
.autocompleter("listen");
|
||||
this.toggle_master_user(group);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide or show the master user checkbox according to desired role.
|
||||
*
|
||||
* @param {string} group - The desired role (or group)
|
||||
*/
|
||||
toggle_master_user: function(group) {
|
||||
var $target = $("#id_master_user").parents(".form-group");
|
||||
if (group !== "SuperAdmins") {
|
||||
$target.hide();
|
||||
} else {
|
||||
$target.show();
|
||||
}
|
||||
},
|
||||
|
||||
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(value);
|
||||
}
|
||||
}, this));
|
||||
this.toggle_master_user($("#id_role").val());
|
||||
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: {
|
||||
"mail": 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_address").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);
|
||||
@@ -0,0 +1,14 @@
|
||||
{% 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.master_user %}{% render_field form.master_user %}{% endif %}
|
||||
{% 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 %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends "common/generic_modal_form.html" %}{% load form_tags %}
|
||||
{% block formbody %}
|
||||
{% render_field form.address %}
|
||||
{% 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 %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% load i18n form_tags %}
|
||||
{% render_field form.name %}
|
||||
{% render_field form.type %}
|
||||
{% render_field form.quota appended_text=_("MB") %}
|
||||
{% render_fields_group form "aliases" %}
|
||||
{% render_field form.enabled %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% 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 %}
|
||||
<div class="alert alert-warning">{% trans "You can't create a new domain administrator" %}</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,63 @@
|
||||
{% extends "admin/header.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load admin_tags %}
|
||||
|
||||
{% block leftcol %}
|
||||
<ul class="nav nav-sidebar">
|
||||
{% domains_menu "statistics" user False %}
|
||||
</ul>
|
||||
|
||||
{% get_extra_admin_content user "leftcol" selection %}
|
||||
{% endblock %}
|
||||
|
||||
{% block apparea %}
|
||||
<h2>{% trans "Statistics" %} <small>{% trans "Domains and identities" %}</small></h2>
|
||||
<hr>
|
||||
|
||||
<div class="row">
|
||||
{% if user.group == "SuperAdmins" %}
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">{% trans "Global counters" %}</h3></div>
|
||||
<div class="panel-body"></div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>{% trans "Type" %}</th>
|
||||
<th>{% trans "Quantity" %}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Domains" %}</td><td>{{ domains_counter }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Domain aliases" %}</td><td>{{ domain_aliases_counter }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Identities" %}</td><td>{{ identities_counter }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">{% trans "Per-domain counters" %}</h3></div>
|
||||
<div class="panel-body"></div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>{% trans "Domain" %}</th>
|
||||
<th>{% trans "Identities" %}</th>
|
||||
</tr>
|
||||
{% for domain in domains %}
|
||||
<tr>
|
||||
<td>{{ domain.name }}</td><td>{{ domain.identities_count }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,29 @@
|
||||
{% 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 }}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
admin = new Domains({
|
||||
load_page_url: "{% url 'admin:_domain_list' %}"
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% extra_static_content "domains" "js" user %}
|
||||
{% endblock %}
|
||||
|
||||
{% block actions %}{% domains_menu "domains" user %}{% endblock %}
|
||||
|
||||
{% block table_header %}
|
||||
<th id="name" class="sortable" data-sort_order="name" width="">{% trans "Name" %}</th>
|
||||
<th id="aliases" width="">{% trans "Alias(es)" %}</th>
|
||||
<th id="tags" class="sortable" data-sort_order="tags" width="">{% trans "Tags" %}</th>
|
||||
<th id="actions" width="">{% trans "Actions" %}</th>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% load i18n admin_tags lib_tags %}
|
||||
{% for domain in domains %}
|
||||
<tr id="{{ domain.id }}" class="{% if not domain.enabled %}text-muted{% endif %}" name="{{ forloop.counter }}">
|
||||
<td name="name">{% domain_modify_link domain %}{% if not domain.enabled %} ({% trans "disabled" %}){% endif %}</td>
|
||||
<td name="aliases">{% domain_aliases domain %} </td>
|
||||
<td name="tags">{% render_tags domain.tags %}</td>
|
||||
<td name="actions">{% domain_actions user domain %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,28 @@
|
||||
{% extends "common/tabforms.html" %}{% load i18n lib_tags admin_tags %}
|
||||
{% block extratabs %}
|
||||
<li class="{% if tabs.active_id == 'admins' %}active{% endif %}">
|
||||
<a href="#admins" data-toggle="tab">{% trans "Administrators" %}</a>
|
||||
</li>
|
||||
<li class="{% if tabs.active_id == 'misc' %}active{% endif %}">
|
||||
<a href="#misc" data-toggle="tab">{% trans "Miscellaneous" %}</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block extratabs_content %}
|
||||
<div class="tab-pane{% if tabs.active_id == 'admins' %} active{% endif %}" id="admins">{% if domadmins %}
|
||||
<table id="domadmins" class="table table-condensed">
|
||||
<tr><th>{% trans "Username" %}</th><th>{% trans "Name" %}</th><th></th></tr>
|
||||
{% for da in domadmins %}<tr>
|
||||
<td>{{ da.username }}</td>
|
||||
<td>{{ da.fullname }}</td>
|
||||
<td name="actions">{% if perms.admin.change_domain %}{% domadmin_actions da.id domain.id %}{% endif %}</td>
|
||||
</tr>{% endfor %}
|
||||
</table>{% else %}<div class="alert alert-info">{% trans "No domain administrator defined" %}</div>{% endif %}
|
||||
</div>
|
||||
<div class="tab-pane{% if tabs.active_id == 'misc' %} active{% endif %}" id="misc">
|
||||
<div class="row"><span class="title">{% trans "Creation date" %}</span><span>{{ domain.creation }}</span></div>
|
||||
<div class="row"><span class="title">{% trans "Last modification date" %}</span><span>{{ domain.last_modification }}</span></div>
|
||||
<div class="row"><span class="title">{% trans "Domain aliases" %}</span><span>{{ domain.domainalias_count }}</span></div>
|
||||
<div class="row"><span class="title">{% trans "Mailboxes" %}</span><span>{{ domain.mailbox_count }}</span></div>
|
||||
<div class="row"><span class="title">{% trans "Mailbox aliases" %}</span><span>{{ domain.mbalias_count }}</span></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% load i18n form_tags %}{% load url from future %}
|
||||
<h2>{% trans "Forward" %} <small>{% trans "Automatically forward emails to another address" %}</small></h2>
|
||||
<hr>
|
||||
<form class="form-horizontal" method="POST" action="{% url 'user_forward' %}"
|
||||
id="uprefs_form">
|
||||
{% csrf_token %}
|
||||
{% render_form form %}
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary col-lg-offset-8 col-md-offset-8 col-sm-offset-7 col-lg-1 col-md-1 col-sm-2" id="update" name="update">{% trans 'Update' %}</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,12 @@
|
||||
{% extends "twocols.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/admin.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script type="text/javascript" src="{% static 'js/history.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/listing.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'admin/js/admin.js' %}"></script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,26 @@
|
||||
{% 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 }}
|
||||
<script type="text/javascript" src="{% static 'js/autocompleter.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
admin = new Identities({
|
||||
domain_list_url: "{% url 'admin:domain_flat_list' %}",
|
||||
load_page_url: "{% url 'admin:identity_page' %}"
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% extra_static_content "identities" "js" user %}
|
||||
{% endblock %}
|
||||
|
||||
{% block actions %}{% identities_menu user "identities" %}{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% load i18n admin_tags lib_tags %}
|
||||
{% for ident in identities %}
|
||||
{% check_identity_status ident as identity_is_enabled %}
|
||||
<tr id="{{ ident.id }}" class="{% if not identity_is_enabled %}text-muted{% endif %}" name="{{ forloop.counter }}">
|
||||
<td name="identity">{% identity_modify_link ident %}{% if not identity_is_enabled %} (disabled){% endif %}</td>
|
||||
<td name="name_or_rcpt">{{ ident.name_or_rcpt }}</td>
|
||||
<td name="tags">{% render_tags ident.tags %}</td>
|
||||
<td name="actions">{% identity_actions user ident %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,5 @@
|
||||
{% load i18n %}
|
||||
<th id="identity" class="sortable" data-sort_order="identity" width="">{% trans "Name" %}</th>
|
||||
<th id="name_or_rcpt" class="sortable" data-sort_order="name_or_rcpt" width="">{% trans "Fullname/Recipient" %}</th>
|
||||
<th id="tags" class="sortable" data-sort_order="tags" width="">{% trans "Tags" %}</th>
|
||||
<th id="actions" width="">{% trans "Actions" %}</th>
|
||||
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head profile="http://www.w3.org/2005/10/profile">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<script type="text/javascript">
|
||||
parent.admin.importdone("{{ status }}", "{{ msg|escapejs }}");
|
||||
</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
@@ -0,0 +1,16 @@
|
||||
{% extends "common/generic_modal_form.html" %}
|
||||
{% load form_tags i18n %}
|
||||
{% load static %}
|
||||
{% block formbody %}
|
||||
<div class="alert alert-info">
|
||||
<h4>{% trans "Help" %}</h4>
|
||||
{{ helptext|safe }}
|
||||
</div>
|
||||
{% render_form form %}
|
||||
<iframe id="import_target" name="import_target" src="#"
|
||||
style="width:0;height:0;border:0px solid #fff;"></iframe>
|
||||
<div id="import_status" style="text-align: center;display:none">
|
||||
<img src="{% static 'css/spinner.gif' %}" /> {% trans "Importing..." %}
|
||||
</div>
|
||||
<div id="import_result"></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,47 @@
|
||||
{% extends "admin/header.html" %}{% load i18n admin_tags %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/jquery.sortable.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript" src="{% static 'js/creation_wizard.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/dynamic_input.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/jquery.sortable.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/jquery.infinitescroll.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
var admin;
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block leftcol %}
|
||||
<ul class="nav nav-sidebar">
|
||||
{% block actions %}{% endblock %}
|
||||
</ul>
|
||||
|
||||
{% get_extra_admin_content user "leftcol" selection %}
|
||||
{% endblock %}
|
||||
|
||||
{% block apparea %}
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
{% include "admin/searchform.html" %}
|
||||
</div>
|
||||
<div id="taglist" class="col-sm-5"> </div>
|
||||
</div>
|
||||
|
||||
<div id="listing">
|
||||
<table id="objects_table" class="table {{ styles }}">
|
||||
<thead>
|
||||
<tr>
|
||||
{% block table_header %}{% endblock %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% load i18n %}
|
||||
{% if target == "permissions" %}
|
||||
<option value="">{% trans "Choose a value" %}</option>
|
||||
{% endif %}
|
||||
{% for mb in mailboxes %}
|
||||
{% if target == "permissions" %}
|
||||
<option value='{{ mb.id }}'>{{ mb.name }}</option>
|
||||
{% else %}
|
||||
<option value='{{ mb.id }}'>{{ mb.full_address }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,5 @@
|
||||
{% 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" %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% 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 %}
|
||||
@@ -0,0 +1,2 @@
|
||||
{% load form_tags %}
|
||||
{% render_fields_group form "domains" %}
|
||||
@@ -0,0 +1,5 @@
|
||||
{% load i18n %}
|
||||
<th width="50%" class="sortable" data-sort_order="address">{% trans "Address" %}</th>
|
||||
<th class="sortable" data-sort_order="quota_value__bytes">{% trans "Value" %}</th>
|
||||
<th class="sortable" data-sort_order="quota">{% trans "Limit" %}</th>
|
||||
<th class="sortable" data-sort_order="quota_usage" id="quotabar">{% trans "Usage (%)" %}</th>
|
||||
@@ -0,0 +1,15 @@
|
||||
{% load lib_tags admin_tags %}
|
||||
|
||||
{% for mbox in mboxes %}
|
||||
<tr>
|
||||
<td>{% identity_modify_link mbox.user "mail" %}</td>
|
||||
<td>{{ mbox.get_quota }}M</td>
|
||||
<td>{{ mbox.quota }}M</td>
|
||||
<td name="quota">
|
||||
<div id="quotabar" rel="tooltip" title="{{ mbox.get_quota_in_percent }}%"
|
||||
class="progress">
|
||||
<div class="{% progress_color mbox.get_quota_in_percent %}" style="width: {{ mbox.get_quota_in_percent }}%"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% load i18n %}
|
||||
<form id="searchform" class="form-horizontal" role="form">
|
||||
<div class="form-group has-feedback">
|
||||
<div class="col-sm-12">
|
||||
<input class="form-control" type="text"
|
||||
value={% if squery %}"{{ squery }}"{% else %}"{% trans 'Search' %}"{% endif %}
|
||||
id="searchquery" name="searchquery" />
|
||||
<span class="fa fa-search form-control-feedback"></span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,286 @@
|
||||
"""
|
||||
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
|
||||
|
||||
from .. import signals
|
||||
|
||||
register = template.Library()
|
||||
|
||||
genders = {
|
||||
"Enabled": (ugettext_lazy("enabled_m"), ugettext_lazy("enabled_f"))
|
||||
}
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def domains_menu(selection, user, ajax_mode=True):
|
||||
"""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 ajax_mode 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 = [
|
||||
{"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"
|
||||
})
|
||||
|
||||
responses = signals.extra_domain_actions.send(
|
||||
sender=None, user=user, domain=domain)
|
||||
for receiver, response in responses:
|
||||
if response:
|
||||
actions += response
|
||||
|
||||
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": "{}?selection={}".format(
|
||||
reverse("admin:alias_delete"), objid),
|
||||
"img": "fa fa-trash",
|
||||
"title": _("Delete %s?" % ident.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 hasattr(identity, "mailbox") \
|
||||
and not identity.mailbox.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<br/>' % 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)
|
||||
@@ -0,0 +1,24 @@
|
||||
"""modoboa-admin unit tests."""
|
||||
|
||||
from .account import AccountTestCase, PermissionsTestCase
|
||||
from .alias import AliasTestCase
|
||||
from .domain import DomainTestCase
|
||||
from .domain_alias import DomainAliasTestCase
|
||||
from .export import ExportTestCase
|
||||
from .import_ import ImportTestCase
|
||||
from .mapfiles import MapFilesTestCase
|
||||
from .password_schemes import PasswordSchemesTestCase
|
||||
from .user import ForwardTestCase
|
||||
|
||||
__all__ = [
|
||||
'AccountTestCase',
|
||||
'AliasTestCase',
|
||||
'DomainTestCase',
|
||||
'DomainAliasTestCase',
|
||||
'ExportTestCase',
|
||||
'ForwardTestCase',
|
||||
'ImportTestCase',
|
||||
'MapFilesTestCase',
|
||||
'PasswordSchemesTestCase',
|
||||
'PermissionsTestCase',
|
||||
]
|
||||
@@ -0,0 +1,249 @@
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
from .. import factories
|
||||
from .. import models
|
||||
|
||||
|
||||
class AccountTestCase(ModoTestCase):
|
||||
|
||||
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="Toto1234", password2="Toto1234", 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
|
||||
self.assertEqual(mb.full_address, "tester@test.com")
|
||||
self.assertEqual(mb.quota, 10)
|
||||
self.assertTrue(mb.enabled)
|
||||
self.assertEqual(mb.quota_value.username, "tester@test.com")
|
||||
self.assertEqual(account.username, mb.full_address)
|
||||
self.assertTrue(account.check_password("Toto1234"))
|
||||
self.assertEqual(account.first_name, "Tester")
|
||||
self.assertEqual(account.last_name, "Toto")
|
||||
self.assertEqual(mb.domain.mailbox_count, 3)
|
||||
# Check if self alias has been created
|
||||
self.assertTrue(
|
||||
models.AliasRecipient.objects.select_related("alias").filter(
|
||||
alias__address=mb.full_address, address=mb.full_address,
|
||||
alias__internal=True).exists()
|
||||
)
|
||||
|
||||
values["username"] = "pouet@test.com"
|
||||
self.ajax_post(
|
||||
reverse("admin:account_change", args=[account.id]), values
|
||||
)
|
||||
mb = models.Mailbox.objects.get(pk=mb.id)
|
||||
self.assertEqual(mb.full_address, "pouet@test.com")
|
||||
self.assertEqual(mb.quota_value.username, "pouet@test.com")
|
||||
# Check if self alias has been updated
|
||||
self.assertTrue(
|
||||
models.AliasRecipient.objects.select_related("alias").filter(
|
||||
alias__address=mb.full_address, address=mb.full_address,
|
||||
alias__internal=True).exists()
|
||||
)
|
||||
self.ajax_post(
|
||||
reverse("admin:account_delete", args=[account.id]), {}
|
||||
)
|
||||
# Check if self alias has been deleted
|
||||
self.assertFalse(
|
||||
models.AliasRecipient.objects.select_related("alias").filter(
|
||||
alias__address=mb.full_address, address=mb.full_address,
|
||||
alias__internal=True).exists()
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
def test_master_user(self):
|
||||
"""Validate the master user mode."""
|
||||
values = {
|
||||
"username": "masteruser", "role": "SuperAdmins",
|
||||
"quota_act": False,
|
||||
"is_active": True, "master_user": True, "stepid": "step2",
|
||||
"password1": "Toto1234", "password2": "Toto1234"
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:account_add"), values
|
||||
)
|
||||
self.assertTrue(User.objects.get(username="masteruser").master_user)
|
||||
|
||||
values = {
|
||||
"username": "testuser", "role": "DomainAdmins",
|
||||
"quota_act": False,
|
||||
"is_active": True, "master_user": True, "stepid": "step2",
|
||||
"password1": "Toto1234", "password2": "Toto1234"
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:account_add"), values, status=400
|
||||
)
|
||||
|
||||
|
||||
class PermissionsTestCase(ModoTestCase):
|
||||
|
||||
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(
|
||||
models.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="Toto1234", password2="Toto1234",
|
||||
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(
|
||||
address="all@test.com",
|
||||
recipients="user@test.com",
|
||||
recipients_1="user@test2.com",
|
||||
enabled=True
|
||||
)
|
||||
self.ajax_post(reverse("admin:dlist_add"), values)
|
||||
|
||||
def test_domainadmin_master_user(self):
|
||||
"""Check domain administrator is not allowed to access this feature."""
|
||||
values = dict(
|
||||
username="user10@test.com", first_name="Test",
|
||||
last_name="Test", password1="Toto1234", password2="Toto1234",
|
||||
role="SimpleUsers", is_active=True, master_user=True,
|
||||
email="user10@test.com", stepid='step2'
|
||||
)
|
||||
self.ajax_post(
|
||||
reverse("admin:account_add"),
|
||||
values, status=400
|
||||
)
|
||||
@@ -0,0 +1,202 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""Admin test cases."""
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
from .. import factories
|
||||
from ..models import Alias, AliasRecipient
|
||||
|
||||
|
||||
class AliasTestCase(ModoTestCase):
|
||||
|
||||
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(
|
||||
AliasRecipient.objects.filter
|
||||
(alias__internal=False, r_mailbox=user.mailbox)
|
||||
.count(), 2
|
||||
)
|
||||
del values["aliases_1"]
|
||||
self.ajax_post(
|
||||
reverse("admin:account_change", args=[user.id]),
|
||||
values
|
||||
)
|
||||
self.assertEqual(
|
||||
AliasRecipient.objects.filter(
|
||||
alias__internal=False, r_mailbox=user.mailbox)
|
||||
.count(), 1
|
||||
)
|
||||
|
||||
def test_alias_with_duplicated_recipient(self):
|
||||
"""Check for duplicates."""
|
||||
values = {
|
||||
"address": "badalias@test.com",
|
||||
"recipients": "user@test.com",
|
||||
"recipients_1": "user@test.com",
|
||||
"enabled": True
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:dlist_add"), values
|
||||
)
|
||||
alias = Alias.objects.get(address="badalias@test.com")
|
||||
self.assertEqual(alias.recipients_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
|
||||
)
|
||||
mb = user.mailbox
|
||||
self.assertEqual(
|
||||
AliasRecipient.objects
|
||||
.filter(alias__internal=False, r_mailbox=mb).count(), 1)
|
||||
self.assertEqual(
|
||||
AliasRecipient.objects.get(
|
||||
alias__internal=False, r_mailbox=mb).alias.address,
|
||||
"toto@test.com"
|
||||
)
|
||||
|
||||
values = {
|
||||
"address": "Titi@test.com", "recipients": "user@test.com",
|
||||
"enabled": True
|
||||
}
|
||||
self.ajax_post(reverse("admin:alias_add"), values)
|
||||
self.assertTrue(
|
||||
Alias.objects.filter(address="titi@test.com").exists())
|
||||
|
||||
def test_append_alias_with_tag(self):
|
||||
"""Try to create a alias with tag in recipient address"""
|
||||
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"
|
||||
)
|
||||
self.ajax_post(
|
||||
reverse("admin:account_change", args=[user.id]),
|
||||
values
|
||||
)
|
||||
|
||||
values = {
|
||||
"address": "foobar@test.com", "recipients": "user+spam@test.com",
|
||||
"enabled": True
|
||||
}
|
||||
self.ajax_post(reverse("admin:alias_add"), values)
|
||||
alias = Alias.objects.get(address="foobar@test.com")
|
||||
self.assertTrue(
|
||||
alias.aliasrecipient_set.filter(
|
||||
address="user+spam@test.com", r_mailbox__isnull=False,
|
||||
r_alias__isnull=True).exists()
|
||||
)
|
||||
|
||||
def test_dlist(self):
|
||||
values = dict(address="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")
|
||||
mb = user.mailbox
|
||||
self.assertEqual(
|
||||
AliasRecipient.objects.filter(
|
||||
alias__internal=False, r_mailbox=mb).count(), 2)
|
||||
admin = User.objects.get(username="admin@test.com")
|
||||
mb = admin.mailbox
|
||||
self.assertEqual(
|
||||
AliasRecipient.objects.filter(
|
||||
alias__internal=False, r_mailbox=mb).count(), 1)
|
||||
dlist = Alias.objects.get(address="all@test.com")
|
||||
self.assertEqual(dlist.recipients_count, 3)
|
||||
del values["recipients_1"]
|
||||
self.ajax_post(
|
||||
reverse("admin:alias_change", args=[dlist.id]),
|
||||
values
|
||||
)
|
||||
self.assertEqual(dlist.recipients_count, 2)
|
||||
|
||||
self.ajax_post(
|
||||
"{}?selection={}".format(
|
||||
reverse("admin:alias_delete"), dlist.id),
|
||||
{}
|
||||
)
|
||||
self.assertRaises(
|
||||
Alias.DoesNotExist, Alias.objects.get, address="all@test.com")
|
||||
|
||||
def test_forward(self):
|
||||
values = dict(address="forward2@test.com", recipients="rcpt@dest.com")
|
||||
self.ajax_post(
|
||||
reverse("admin:forward_add"), values
|
||||
)
|
||||
fwd = Alias.objects.get(address="forward2@test.com")
|
||||
self.assertEqual(fwd.recipients_count, 1)
|
||||
|
||||
values["recipients"] = "rcpt2@dest.com"
|
||||
self.ajax_post(
|
||||
reverse("admin:alias_change",
|
||||
args=[fwd.id]),
|
||||
values
|
||||
)
|
||||
self.assertEqual(fwd.recipients_count, 1)
|
||||
|
||||
self.ajax_post(
|
||||
reverse("admin:alias_delete") + "?selection=%d"
|
||||
% fwd.id, {}
|
||||
)
|
||||
self.assertRaises(
|
||||
Alias.DoesNotExist, Alias.objects.get, address="forward2@test.com")
|
||||
|
||||
def test_forward_and_local_copies(self):
|
||||
values = dict(address="user@test.com", recipients="rcpt@dest.com")
|
||||
self.ajax_post(
|
||||
reverse("admin:forward_add"), values
|
||||
)
|
||||
fwd = Alias.objects.get(address="user@test.com", internal=False)
|
||||
self.assertEqual(fwd.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.aliasrecipient_set.count(), 2)
|
||||
self.assertEqual(
|
||||
fwd.aliasrecipient_set.filter(r_alias__isnull=True).count(), 2)
|
||||
|
||||
def test_wildcard_alias(self):
|
||||
"""Test creation of a wildcard alias."""
|
||||
values = {
|
||||
"address": "@test.com",
|
||||
"recipients": "user@test.com",
|
||||
"enabled": True
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:dlist_add"), values
|
||||
)
|
||||
@@ -0,0 +1,131 @@
|
||||
"""Domain related test cases."""
|
||||
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
from .. import factories
|
||||
from ..models import Domain, Alias
|
||||
|
||||
|
||||
class DomainTestCase(ModoTestCase):
|
||||
|
||||
"""Test case for Domain."""
|
||||
|
||||
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",
|
||||
"type": "domain", "stepid": "step3"
|
||||
}
|
||||
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",
|
||||
"type": "domain", "stepid": 'step3'
|
||||
}
|
||||
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@pouet.com")
|
||||
self.assertTrue(
|
||||
al.aliasrecipient_set.filter(r_mailbox=da.mailbox)
|
||||
.exists()
|
||||
)
|
||||
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",
|
||||
"type": "domain", "stepid": 'step3'
|
||||
}
|
||||
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@pouet.com")
|
||||
self.assertTrue(
|
||||
al.aliasrecipient_set.filter(r_mailbox=da.mailbox)
|
||||
.exists()
|
||||
)
|
||||
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",
|
||||
"type": "domain", "stepid": 'step3'
|
||||
}
|
||||
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.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, "type": "domain",
|
||||
"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)
|
||||
|
||||
def test_domain_flat_list(self):
|
||||
"""Test the 'domain_flat_list' view."""
|
||||
response = self.clt.get(reverse("admin:domain_flat_list"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
content = json.loads(response.content)
|
||||
self.assertIn("test.com", content)
|
||||
self.assertIn("test2.com", content)
|
||||
@@ -0,0 +1,55 @@
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
from .. import factories
|
||||
from ..models import Domain, DomainAlias, Alias
|
||||
|
||||
|
||||
class DomainAliasTestCase(ModoTestCase):
|
||||
|
||||
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)
|
||||
self.assertTrue(
|
||||
Alias.objects.filter(
|
||||
address="@{}".format(domal.name)).exists())
|
||||
|
||||
domal.name = "domalias.org"
|
||||
domal.save()
|
||||
|
||||
domal.delete()
|
||||
self.assertFalse(
|
||||
Alias.objects.filter(
|
||||
address="@{}".format(domal.name)).exists())
|
||||
|
||||
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",
|
||||
type="domain"
|
||||
)
|
||||
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)
|
||||
@@ -0,0 +1,94 @@
|
||||
"""Export related test cases."""
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
from .. import factories
|
||||
|
||||
|
||||
class ExportTestCase(ModoTestCase):
|
||||
|
||||
"""Test case for export operations."""
|
||||
|
||||
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@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):
|
||||
"""A test to validate we only export 1 super admin.
|
||||
|
||||
The password is removed since it is hashed using SHA512-CRYPT.
|
||||
"""
|
||||
response = self.__export_identities(
|
||||
idtfilter="account", grpfilter="SuperAdmins"
|
||||
)
|
||||
elements = response.content.strip().split(";")
|
||||
self.assertEqual(len(elements), 9)
|
||||
elements[2] = ""
|
||||
self.assertEqual(
|
||||
";".join(elements), "account;admin;;;;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"
|
||||
)
|
||||
@@ -0,0 +1,237 @@
|
||||
# coding: utf-8
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
from .. import factories
|
||||
from ..models import Domain, Alias, DomainAlias
|
||||
|
||||
|
||||
class ImportTestCase(ModoTestCase):
|
||||
|
||||
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; alias2@test.com; True; user1+ext@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
|
||||
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
|
||||
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@test.com")
|
||||
self.assertTrue(
|
||||
al.aliasrecipient_set
|
||||
.filter(r_mailbox=u1.mailbox).exists()
|
||||
)
|
||||
self.assertTrue(admin.is_owner(al))
|
||||
|
||||
fwd = Alias.objects.get(address="fwd1@test.com")
|
||||
self.assertTrue(
|
||||
fwd.aliasrecipient_set
|
||||
.filter(
|
||||
address="user@extdomain.com", r_mailbox__isnull=True,
|
||||
r_alias__isnull=True)
|
||||
.exists()
|
||||
)
|
||||
self.assertTrue(admin.is_owner(fwd))
|
||||
|
||||
dlist = Alias.objects.get(address="dlist@test.com")
|
||||
self.assertTrue(
|
||||
dlist.aliasrecipient_set
|
||||
.filter(r_mailbox=u1.mailbox).exists()
|
||||
)
|
||||
self.assertTrue(
|
||||
dlist.aliasrecipient_set.filter(address="user@extdomain.com")
|
||||
.exists()
|
||||
)
|
||||
self.assertTrue(admin.is_owner(dlist))
|
||||
|
||||
def test_import_for_nonlocal_domain(self):
|
||||
"""Try to import an account for nonlocal domain."""
|
||||
f = ContentFile(b"""
|
||||
account; user1@nonlocal.com; toto; User; One; True; SimpleUsers; user1@nonlocal.com; 0
|
||||
""", name="identities.csv")
|
||||
self.clt.post(
|
||||
reverse("admin:identity_import"),
|
||||
{"sourcefile": f, "crypt_password": True}
|
||||
)
|
||||
self.assertFalse(
|
||||
User.objects.filter(username="user1@nonlocal.com").exists())
|
||||
|
||||
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_domain_by_domainadmin(self):
|
||||
"""Check if a domain admin is not allowed to import a domain."""
|
||||
self.clt.logout()
|
||||
self.clt.login(username="admin@test.com", password="toto")
|
||||
f = ContentFile(b"""
|
||||
domain; domain2.com; 200; False
|
||||
""", name="identities.csv")
|
||||
resp = self.clt.post(
|
||||
reverse("admin:identity_import"),
|
||||
{"sourcefile": f, "crypt_password": True}
|
||||
)
|
||||
self.assertIn("You are not allowed to import domains", resp.content)
|
||||
f = ContentFile(b"""
|
||||
domainalias; domalias1.com; test.com; True
|
||||
""", name="identities.csv")
|
||||
resp = self.clt.post(
|
||||
reverse("admin:identity_import"),
|
||||
{"sourcefile": f, "crypt_password": True}
|
||||
)
|
||||
self.assertIn(
|
||||
"You are not allowed to import domain aliases", 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.quota,
|
||||
account.mailbox.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(address="user.alias@test.com")
|
||||
self.assertEqual(alias.type, "alias")
|
||||
@@ -0,0 +1,15 @@
|
||||
"""Test map files generation."""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from modoboa.lib.test_utils import MapFilesTestCaseMixin
|
||||
|
||||
|
||||
class MapFilesTestCase(MapFilesTestCaseMixin, TestCase):
|
||||
|
||||
"""Test case for admin."""
|
||||
|
||||
MAP_FILES = [
|
||||
"sql-domains.cf", "sql-domain-aliases.cf", "sql-aliases.cf",
|
||||
"sql-maintain.cf"
|
||||
]
|
||||
@@ -0,0 +1,57 @@
|
||||
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 .. 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="Toto1234", password2="Toto1234", 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('Toto1234'))
|
||||
|
||||
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}')
|
||||
@@ -0,0 +1,27 @@
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
from ..factories import populate_database
|
||||
from ..models import Alias
|
||||
|
||||
|
||||
class ForwardTestCase(ModoTestCase):
|
||||
|
||||
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@test.com', internal=False)
|
||||
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))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user