mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
added pdfcredential native support
This commit is contained in:
@@ -164,6 +164,17 @@ export default {
|
||||
getMenuItems (item) {
|
||||
const result = []
|
||||
if (item.type === 'account') {
|
||||
item.possible_actions.forEach(element => {
|
||||
result.push({
|
||||
label: this.$gettext(element.label),
|
||||
icon: element.icon,
|
||||
link: element.url,
|
||||
onClick: () => {
|
||||
window.open(element.url)
|
||||
this.fetchIdentities()
|
||||
}
|
||||
})
|
||||
})
|
||||
result.push({ label: this.$gettext('Edit'), icon: 'mdi-circle-edit-outline', onClick: this.editAccount })
|
||||
result.push({ label: this.$gettext('Delete'), icon: 'mdi-delete-outline', onClick: this.deleteAccount, color: 'red' })
|
||||
} else if (item.type === 'alias') {
|
||||
|
||||
@@ -14,6 +14,7 @@ from django.contrib.auth import password_validation
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from modoboa.admin import signals as admin_signals
|
||||
from modoboa.admin.api.v1 import serializers as v1_serializers
|
||||
from modoboa.core import models as core_models, signals as core_signals
|
||||
from modoboa.lib import email_utils
|
||||
@@ -284,6 +285,15 @@ class TagSerializer(serializers.Serializer):
|
||||
type = serializers.CharField()
|
||||
|
||||
|
||||
class IdPossibleActionsSerializer(serializers.Serializer):
|
||||
"""Serialiser used to get possible actions related to identities."""
|
||||
|
||||
name = serializers.CharField()
|
||||
icon = serializers.CharField()
|
||||
label = serializers.CharField()
|
||||
url = serializers.URLField()
|
||||
|
||||
|
||||
class IdentitySerializer(serializers.Serializer):
|
||||
"""Serializer used for identities."""
|
||||
|
||||
@@ -293,6 +303,24 @@ class IdentitySerializer(serializers.Serializer):
|
||||
name_or_rcpt = serializers.CharField()
|
||||
tags = TagSerializer(many=True)
|
||||
|
||||
def __init__(self, instance=None, data=..., **kwargs):
|
||||
super().__init__(instance, data, **kwargs)
|
||||
self.fields["possible_actions"] = serializers.SerializerMethodField()
|
||||
|
||||
def get_possible_actions(self, identity):
|
||||
if not isinstance(identity, core_models.User):
|
||||
# Return empty action list if identity type is an alias (not used for now)
|
||||
return []
|
||||
actions = admin_signals.extra_account_identities_actions.send(
|
||||
self.__class__, account=identity)
|
||||
cleaned_actions = []
|
||||
for action in actions:
|
||||
try :
|
||||
serialized_data = IdPossibleActionsSerializer(action[1]).data
|
||||
cleaned_actions.append(serialized_data)
|
||||
except (ValidationError, AttributeError):
|
||||
continue
|
||||
return cleaned_actions
|
||||
|
||||
class AccountResourceSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for user resource."""
|
||||
@@ -512,7 +540,7 @@ class WritableAccountSerializer(v1_serializers.WritableAccountSerializer):
|
||||
instance.set_password(password)
|
||||
if mailbox_data:
|
||||
creator = self.context["request"].user
|
||||
if hasattr(instance, "mailbox"):
|
||||
if hasattr(instance, "mailbox") and "mailbox" in validated_data:
|
||||
if "username" in validated_data:
|
||||
mailbox_data["email"] = validated_data["username"]
|
||||
instance.email = validated_data["username"]
|
||||
|
||||
@@ -29,3 +29,4 @@ get_domain_form_instances = django.dispatch.Signal(
|
||||
import_object = django.dispatch.Signal(providing_args=["objtype"])
|
||||
use_external_recipients = django.dispatch.Signal(providing_args=["recipients"])
|
||||
new_dkim_keys = django.dispatch.Signal(providing_args=["domains"])
|
||||
extra_account_identities_actions = django.dispatch.Signal(providing_args=["account"])
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Core settings."""
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
import collections
|
||||
|
||||
from django import forms
|
||||
@@ -536,7 +534,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
|
||||
]
|
||||
|
||||
def _add_dynamic_fields(self):
|
||||
new_fields = OrderedDict()
|
||||
new_fields = collections.OrderedDict()
|
||||
for field, value in self.fields.items():
|
||||
new_fields[field] = value
|
||||
if field == "sms_provider":
|
||||
|
||||
@@ -87,6 +87,7 @@ MODOBOA_APPS = (
|
||||
'modoboa.dnstools',
|
||||
'modoboa.policyd',
|
||||
'modoboa.maillog',
|
||||
'modoboa.pdfcredentials',
|
||||
# Modoboa extensions here.
|
||||
{% for extension in extensions %} '{{ extension }}',
|
||||
{% endfor %}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"""Generate PDF documents containing user credentials."""
|
||||
|
||||
default_app_config = "modoboa.pdfcredentials.apps.PDFCredentialsConfig"
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Handlers for PDF credientials api v2."""
|
||||
|
||||
import os
|
||||
|
||||
from django.urls import reverse
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.admin import signals as admin_signals
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from ...lib import get_creds_filename
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_account_identities_actions)
|
||||
def extra_identities_actions(sender, account, **kwargs):
|
||||
"""
|
||||
Add download credential action for identity.
|
||||
Used for api v2.
|
||||
"""
|
||||
if not param_tools.get_global_parameter("enabled_pdfcredentials"):
|
||||
return []
|
||||
fname = get_creds_filename(account)
|
||||
if not os.path.exists(fname):
|
||||
return []
|
||||
return {
|
||||
"name": "get_credentials",
|
||||
"url": reverse("v2:get-credentials",
|
||||
args=[account.id]),
|
||||
"icon": "mdi-file-download-outline",
|
||||
"label": _("Download PDF credentials.")
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
"""Limits serializers for API v2."""
|
||||
|
||||
import os
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from rest_framework import serializers, status
|
||||
from rest_framework.exceptions import PermissionDenied, APIException
|
||||
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.parameters import tools as param_tools
|
||||
from ...lib import decrypt_file, get_creds_filename
|
||||
|
||||
from ...constants import CONNECTION_SECURITY_MODES
|
||||
|
||||
|
||||
class PDFCredentialsSettingsSerializer(serializers.Serializer):
|
||||
"""A serializer for global parameters."""
|
||||
|
||||
# General
|
||||
enabled_pdfcredentials = serializers.BooleanField(default=True)
|
||||
|
||||
# Document storage
|
||||
storage_dir = serializers.CharField(default="/var/lib/modoboa/pdf_credentials")
|
||||
|
||||
# Security options
|
||||
delete_first_dl = serializers.BooleanField(default=True)
|
||||
generate_at_creation = serializers.BooleanField(default=True)
|
||||
|
||||
# Customization options
|
||||
title = serializers.CharField(default=_("Personal account information"))
|
||||
webpanel_url = serializers.URLField()
|
||||
custom_message = serializers.CharField(required=False, allow_blank=True)
|
||||
include_connection_settings = serializers.BooleanField(default=False)
|
||||
smtp_server_address = serializers.CharField()
|
||||
smtp_server_port = serializers.IntegerField(default=587)
|
||||
smtp_connection_security = serializers.ChoiceField(choices=CONNECTION_SECURITY_MODES, default="starttls")
|
||||
imap_server_address = serializers.CharField()
|
||||
imap_server_port = serializers.IntegerField(default=143)
|
||||
imap_connection_security = serializers.ChoiceField(choices=CONNECTION_SECURITY_MODES, default="starttls")
|
||||
|
||||
|
||||
class GetAccountCredentialsSerializer(serializers.Serializer):
|
||||
"""A serializer for get account credential view."""
|
||||
|
||||
account_id = serializers.IntegerField()
|
||||
|
||||
def validate(self, data):
|
||||
request = self.context["request"]
|
||||
account = User.objects.get(pk=data["account_id"])
|
||||
if not request.user.can_access(account):
|
||||
raise PermissionDenied()
|
||||
self.context["account"] = account
|
||||
return data
|
||||
|
||||
|
||||
def save(self):
|
||||
fname = get_creds_filename(self.context["account"])
|
||||
if not os.path.exists(fname):
|
||||
raise APIException( _("No document available for this user"), status.HTTP_400_BAD_REQUEST)
|
||||
self.context["content"] = decrypt_file(fname)
|
||||
if param_tools.get_global_parameter("delete_first_dl"):
|
||||
os.remove(fname)
|
||||
self.context["fname"] = fname
|
||||
@@ -0,0 +1,153 @@
|
||||
"""API v2 tests."""
|
||||
|
||||
import tempfile
|
||||
import shutil
|
||||
import os
|
||||
|
||||
from django.test import override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
from modoboa.admin import factories
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib.tests import ModoAPITestCase
|
||||
|
||||
|
||||
class PDFCredentialViewTestCase(ModoAPITestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def setUp(self):
|
||||
"""Create temp. directory to store files."""
|
||||
super().setUp()
|
||||
self.workdir = tempfile.mkdtemp()
|
||||
self.set_global_parameter("storage_dir", self.workdir)
|
||||
|
||||
def tearDown(self):
|
||||
"""Reset test env."""
|
||||
shutil.rmtree(self.workdir)
|
||||
|
||||
def _create_account(self, username, expected_status=201):
|
||||
url = reverse("v2:account-list")
|
||||
data = {
|
||||
"username": f"{username}",
|
||||
"role": "SimpleUsers",
|
||||
"mailbox": {
|
||||
"use_domain_quota": True
|
||||
},
|
||||
"password": "Toto12345",
|
||||
"language": "fr",
|
||||
}
|
||||
resp = self.client.post(url, data, format="json")
|
||||
self.assertEqual(resp.status_code, expected_status)
|
||||
return data
|
||||
|
||||
def test_password_updated(self):
|
||||
"""Check that document is generated at account creation/update."""
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
account = core_models.User.objects.get(username=values["username"])
|
||||
|
||||
# Check if link is present in listing page
|
||||
response = self.client.get(reverse("v2:identities-list"), format="json")
|
||||
assert_action_in_response = False
|
||||
for res_dict in response.json():
|
||||
for action in res_dict["possible_actions"]:
|
||||
try:
|
||||
if action.get("icon") == "mdi-file-download-outline":
|
||||
assert_action_in_response = True
|
||||
break
|
||||
except KeyError:
|
||||
continue
|
||||
self.assertEqual(assert_action_in_response, True)
|
||||
|
||||
# Try to download the file
|
||||
response = self.client.get(
|
||||
reverse("v2:get-credentials",
|
||||
args=[account.pk]))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response["Content-Type"], "application/pdf")
|
||||
|
||||
# File have been deleted?
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
# Try to download a second time
|
||||
response = self.client.get(
|
||||
reverse("v2:get-credentials",
|
||||
args=[account.pk]))
|
||||
self.assertEqual(response.json()["detail"], "No document available for this user")
|
||||
|
||||
# Update account
|
||||
values.update({"language": "en"})
|
||||
self.client.patch(
|
||||
reverse("v2:account-detail", args=[account.pk]), values, format='json'
|
||||
)
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
self.set_global_parameter("generate_at_creation", False)
|
||||
self.client.patch(
|
||||
reverse("v2:account-detail", args=[account.pk]), values, format='json'
|
||||
)
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
|
||||
def test_with_connection_settings(self):
|
||||
"""Add connection settings to documents."""
|
||||
self.set_global_parameter("include_connection_settings", True)
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
|
||||
def test_with_custom_message(self):
|
||||
"""Add custom message to documents."""
|
||||
self.set_global_parameter("custom_message", "This is a test message.")
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
|
||||
def test_account_delete(self):
|
||||
"""Check that document is deleted with account."""
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
account = core_models.User.objects.get(username=values["username"])
|
||||
url = reverse("v2:account-delete", args=[account.pk])
|
||||
self.client.post(url)
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
@override_settings(MODOBOA_LOGO="modoboa.png")
|
||||
def test_with_custom_logo(self):
|
||||
"""Check that document is deleted with account."""
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
|
||||
def test_download_and_delete_account(self):
|
||||
"""Check that document is deleted with account."""
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
account = core_models.User.objects.get(username=values["username"])
|
||||
|
||||
# Try to download the file
|
||||
response = self.client.get(
|
||||
reverse("v2:get-credentials",
|
||||
args=[account.pk]))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response["Content-Type"], "application/pdf")
|
||||
|
||||
# File have been deleted?
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
# Delete account
|
||||
url = reverse("v2:account-delete", args=[account.pk])
|
||||
self.client.post(url)
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
def test_storage_dir_creation(self):
|
||||
"""Test storage directory creation."""
|
||||
self.set_global_parameter("storage_dir", "/nonexistentdir")
|
||||
self._create_account("leon@test.com", expected_status=500)
|
||||
@@ -0,0 +1,11 @@
|
||||
"""PDF Credentials API urls."""
|
||||
|
||||
from django.urls import path
|
||||
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('credentials/<int:account_id>/', views.PDFCredentialView.as_view(),
|
||||
name="get-credentials"),
|
||||
]
|
||||
@@ -0,0 +1,39 @@
|
||||
"""PDF Credentials API v2 views."""
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.http import HttpResponse
|
||||
|
||||
from rest_framework import permissions
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from modoboa.admin.models import Domain
|
||||
|
||||
from .serializers import GetAccountCredentialsSerializer
|
||||
|
||||
|
||||
class PDFCredentialView(APIView):
|
||||
|
||||
permission_classes = (
|
||||
permissions.IsAuthenticated, permissions.DjangoModelPermissions,
|
||||
)
|
||||
|
||||
serializer_class = GetAccountCredentialsSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter queryset based on current user."""
|
||||
return Domain.objects.get_for_admin(self.request.user)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""View to download a document."""
|
||||
data = {"account_id": kwargs["account_id"]}
|
||||
serializer = GetAccountCredentialsSerializer(data=data, context={'request': request})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
|
||||
content = serializer.context["content"]
|
||||
fname = serializer.context["fname"]
|
||||
resp = HttpResponse(content)
|
||||
resp["Content-Type"] = "application/pdf"
|
||||
resp["Content-Length"] = len(content)
|
||||
resp["Content-Disposition"] = f"attachment; filename={fname};"
|
||||
return resp
|
||||
@@ -0,0 +1,243 @@
|
||||
"""PDF Credentials forms."""
|
||||
|
||||
import collections
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from django.contrib.sites import models as sites_models
|
||||
|
||||
from modoboa.lib import form_utils
|
||||
from modoboa.parameters import forms as param_forms
|
||||
|
||||
from . import constants
|
||||
|
||||
|
||||
PDF_CREDENTIALS_PARAMETERS_STRUCT = collections.OrderedDict([
|
||||
("general", {
|
||||
"label": _("General"),
|
||||
"params": collections.OrderedDict([
|
||||
("enabled_pdfcredentials", {
|
||||
"label": _("Enable PDF credentials"),
|
||||
"help_text": _(
|
||||
"Enabled PDF credentials document generation on account creation."),
|
||||
})
|
||||
])
|
||||
}),
|
||||
("docstore", {
|
||||
"label": _("Documents storage"),
|
||||
"params": collections.OrderedDict([
|
||||
("storage_dir", {
|
||||
"label": _("Directory to save documents into"),
|
||||
"help_text": _(
|
||||
"Path to a directory where PDF documents will be saved"),
|
||||
}),
|
||||
])
|
||||
}),
|
||||
("security", {
|
||||
"label": _("Security options"),
|
||||
"params": collections.OrderedDict([
|
||||
("delete_first_dl", {
|
||||
"label": _("Delete documents after the first download"),
|
||||
"help_text": _(
|
||||
"Automatically delete a document just after its first download "
|
||||
"from this interface"
|
||||
)
|
||||
}),
|
||||
("generate_at_creation", {
|
||||
"label": _("Generate documents only at account creation"),
|
||||
"help_text": _(
|
||||
"Generate a new document only when a new account is created. "
|
||||
"If set to no, a new document will be created each time a "
|
||||
"password is updated."
|
||||
)
|
||||
})
|
||||
])
|
||||
}),
|
||||
("customization", {
|
||||
"label": _("Customization options"),
|
||||
"params": collections.OrderedDict([
|
||||
("title", {
|
||||
"label": _("Title"),
|
||||
"help_text": _("The document's title")
|
||||
}),
|
||||
("webpanel_url", {
|
||||
"label": _("Web panel url"),
|
||||
"help_text": _("URL of the Modoboa web panel")
|
||||
}),
|
||||
("custom_message", {
|
||||
"label": _("Custom message"),
|
||||
"help_text": _(
|
||||
"A custom message that will appear at the end of documents"
|
||||
)
|
||||
}),
|
||||
("include_connection_settings", {
|
||||
"label": _("Include mail client connection settings"),
|
||||
"help_text": _(
|
||||
"Include required SMTP and IMAP connection information to "
|
||||
"configure a mail client, a tablet or a phone"
|
||||
)
|
||||
}),
|
||||
("smtp_server_address", {
|
||||
"label": _("SMTP server address"),
|
||||
"help_text": _("Address of the SMTP server (hostname or IP)")
|
||||
}),
|
||||
("smtp_server_port", {
|
||||
"label": _("SMTP server port"),
|
||||
"help_port": _("Listening port of the SMTP server")
|
||||
}),
|
||||
("smtp_connection_security", {
|
||||
"label": _("SMTP connection security"),
|
||||
"help_text": _("Connection security mechanism")
|
||||
}),
|
||||
("imap_server_address", {
|
||||
"label": _("IMAP server address"),
|
||||
"help_text": _("Address of the IMAP server (hostname or IP)")
|
||||
}),
|
||||
("imap_server_port", {
|
||||
"label": _("IMAP server port"),
|
||||
"help_text": _("Listening port of the IMAP server")
|
||||
}),
|
||||
("imap_connection_security", {
|
||||
"label": _("IMAP connection security"),
|
||||
"help_text": _("Connection security mechanism")
|
||||
})
|
||||
])
|
||||
})
|
||||
])
|
||||
|
||||
|
||||
|
||||
class ParametersForm(param_forms.AdminParametersForm):
|
||||
"""Admin parameters form."""
|
||||
|
||||
app = "pdfcredentials"
|
||||
|
||||
general = form_utils.SeparatorField(label=_("General"))
|
||||
|
||||
enabled_pdfcredentials = form_utils.YesNoField(
|
||||
label= _("Enable PDF credentials"),
|
||||
initial=True,
|
||||
help_text=_("Enabled PDF credentials document generation on account creation.")
|
||||
)
|
||||
|
||||
docstore = form_utils.SeparatorField(label=_("Documents storage"))
|
||||
|
||||
storage_dir = forms.CharField(
|
||||
label=_("Directory to save documents into"),
|
||||
initial="/var/lib/modoboa/pdf_credentials",
|
||||
help_text=_("Path to a directory where PDF documents will be saved"),
|
||||
)
|
||||
|
||||
security = form_utils.SeparatorField(label=_("Security options"))
|
||||
|
||||
delete_first_dl = form_utils.YesNoField(
|
||||
label=_("Delete documents after the first download"),
|
||||
initial=True,
|
||||
help_text=_(
|
||||
"Automatically delete a document just after its first download "
|
||||
"from this interface"
|
||||
)
|
||||
)
|
||||
|
||||
generate_at_creation = form_utils.YesNoField(
|
||||
label=_("Generate documents only at account creation"),
|
||||
initial=True,
|
||||
help_text=_(
|
||||
"Generate a new document only when a new account is created. "
|
||||
"If set to no, a new document will be created each time a "
|
||||
"password is updated."
|
||||
)
|
||||
)
|
||||
|
||||
customization = form_utils.SeparatorField(label=_("Customization options"))
|
||||
|
||||
title = forms.CharField(
|
||||
label=_("Title"),
|
||||
initial=_("Personal account information"),
|
||||
help_text=_("The document's title")
|
||||
)
|
||||
|
||||
webpanel_url = forms.URLField(
|
||||
label=_("Web panel url"),
|
||||
help_text=_("URL of the Modoboa web panel")
|
||||
)
|
||||
|
||||
custom_message = forms.CharField(
|
||||
label=_("Custom message"),
|
||||
help_text=_(
|
||||
"A custom message that will appear at the end of documents"),
|
||||
required=False
|
||||
)
|
||||
|
||||
include_connection_settings = form_utils.YesNoField(
|
||||
label=_("Include mail client connection settings"),
|
||||
initial=False,
|
||||
help_text=_(
|
||||
"Include required SMTP and IMAP connection information to "
|
||||
"configure a mail client, a tablet or a phone"
|
||||
)
|
||||
)
|
||||
|
||||
smtp_server_address = forms.CharField(
|
||||
label=_("SMTP server address"),
|
||||
help_text=_("Address of the SMTP server (hostname or IP)")
|
||||
)
|
||||
|
||||
smtp_server_port = forms.IntegerField(
|
||||
label=_("SMTP server port"),
|
||||
initial=587,
|
||||
help_text=_("Listening port of the SMTP server")
|
||||
)
|
||||
|
||||
smtp_connection_security = forms.ChoiceField(
|
||||
label=_("SMTP connection security"),
|
||||
choices=constants.CONNECTION_SECURITY_MODES,
|
||||
initial="starttls",
|
||||
help_text=_("Connection security mechanism")
|
||||
)
|
||||
|
||||
imap_server_address = forms.CharField(
|
||||
label=_("IMAP server address"),
|
||||
help_text=_("Address of the IMAP server (hostname or IP)")
|
||||
)
|
||||
|
||||
imap_server_port = forms.IntegerField(
|
||||
label=_("IMAP server port"),
|
||||
initial=143,
|
||||
help_text=_("Listening port of the IMAP server")
|
||||
)
|
||||
|
||||
imap_connection_security = forms.ChoiceField(
|
||||
label=_("IMAP connection security"),
|
||||
choices=constants.CONNECTION_SECURITY_MODES,
|
||||
initial="starttls",
|
||||
help_text=_("Connection security mechanism")
|
||||
)
|
||||
|
||||
visibility_rules = {
|
||||
"smtp_server_address": "include_connection_settings=True",
|
||||
"smtp_server_port": "include_connection_settings=True",
|
||||
"smtp_connection_security": "include_connection_settings=True",
|
||||
"imap_server_address": "include_connection_settings=True",
|
||||
"imap_server_port": "include_connection_settings=True",
|
||||
"imap_connection_security": "include_connection_settings=True",
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def hostname(self):
|
||||
"""Return local hostname."""
|
||||
return sites_models.Site.objects.get_current().domain
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Set initial values."""
|
||||
super(ParametersForm, self).__init__(*args, **kwargs)
|
||||
if not self.fields["webpanel_url"].initial:
|
||||
url = "https://{}{}".format(self.hostname, settings.LOGIN_URL)
|
||||
self.fields["webpanel_url"].initial = url
|
||||
if not self.fields["smtp_server_address"].initial:
|
||||
self.fields["smtp_server_address"].initial = self.hostname
|
||||
if not self.fields["imap_server_address"].initial:
|
||||
self.fields["imap_server_address"].initial = self.hostname
|
||||
@@ -0,0 +1,35 @@
|
||||
"""AppConfig for PDF credentials."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
|
||||
def load_pdfcredential_settings():
|
||||
"""Load core settings.
|
||||
|
||||
This function must be manually called (see :file:`urls.py`) in
|
||||
order to load base settings.
|
||||
"""
|
||||
from modoboa.parameters import tools as param_tools
|
||||
from . import app_settings
|
||||
from .api.v2 import serializers
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", app_settings.ParametersForm, ugettext_lazy("PDF credentials"))
|
||||
param_tools.registry.add2(
|
||||
"global", "pdfcredentials", ugettext_lazy("PDF Credentials"),
|
||||
app_settings.PDF_CREDENTIALS_PARAMETERS_STRUCT,
|
||||
serializers.PDFCredentialsSettingsSerializer)
|
||||
|
||||
|
||||
class PDFCredentialsConfig(AppConfig):
|
||||
"""App configuration."""
|
||||
|
||||
name = "modoboa.pdfcredentials"
|
||||
verbose_name = "PDF credentials for Modoboa"
|
||||
|
||||
def ready(self):
|
||||
from . import handlers
|
||||
from .api.v2 import handlers
|
||||
load_pdfcredential_settings()
|
||||
@@ -0,0 +1,10 @@
|
||||
"""PDF credentials constants."""
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
|
||||
CONNECTION_SECURITY_MODES = [
|
||||
("none", ugettext_lazy("None")),
|
||||
("starttls", "STARTTLS"),
|
||||
("tls", "TLS")
|
||||
]
|
||||
@@ -0,0 +1,131 @@
|
||||
"""The code used to generate PDF files (based on Reportlab)."""
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
from reportlab.lib import colors
|
||||
from reportlab.lib.pagesizes import A4
|
||||
from reportlab.lib.units import cm
|
||||
from reportlab.lib.enums import TA_CENTER
|
||||
from reportlab.lib import utils
|
||||
from reportlab.platypus import (
|
||||
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Frame,
|
||||
Image
|
||||
)
|
||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from . import lib
|
||||
|
||||
styles = getSampleStyleSheet()
|
||||
styles.add(ParagraphStyle(
|
||||
name="Footer", alignment=TA_CENTER, fontName="Helvetica-Oblique",
|
||||
textColor=colors.lightgrey
|
||||
))
|
||||
styles.add(ParagraphStyle(
|
||||
name="Warning", fontName="Helvetica-Oblique",
|
||||
textColor=colors.red, fontSize=12
|
||||
))
|
||||
styles.add(ParagraphStyle(
|
||||
name="Link",
|
||||
textColor=colors.blue
|
||||
))
|
||||
styles.add(ParagraphStyle(
|
||||
name="Greeting", alignment=TA_CENTER, fontName="Helvetica-Oblique",
|
||||
fontSize=14
|
||||
))
|
||||
|
||||
|
||||
def resized_image(path, width=1*cm):
|
||||
img = utils.ImageReader(path)
|
||||
iw, ih = img.getSize()
|
||||
aspect = ih / float(iw)
|
||||
return Image(path, width=width, height=(width * aspect))
|
||||
|
||||
|
||||
def credentials(account, password):
|
||||
"""Generate a PDF document containing account credentials."""
|
||||
|
||||
def page_template(canvas, doc):
|
||||
canvas.setTitle(_("Personal account information"))
|
||||
canvas.setAuthor(account.fullname)
|
||||
canvas.setCreator("Modoboa")
|
||||
footer = [Paragraph(_("Powered by Modoboa - Mail hosting made simple"),
|
||||
styles["Footer"])]
|
||||
Frame(0, 0, 21 * cm, 2 * cm).addFromList(footer, canvas)
|
||||
|
||||
conf = dict(
|
||||
param_tools.get_global_parameters("pdfcredentials"))
|
||||
filename = lib.get_creds_filename(account)
|
||||
buff = BytesIO()
|
||||
doc = SimpleDocTemplate(buff, pagesize=A4)
|
||||
story = []
|
||||
story.append(resized_image(lib.get_document_logo(), 8*cm))
|
||||
story.append(Spacer(1, 1 * cm))
|
||||
story.append(Paragraph(conf["title"], styles["Title"]))
|
||||
story.append(Spacer(1, 1 * cm))
|
||||
story.append(Paragraph(_("""
|
||||
Dear %s, this document contains the credentials you will need
|
||||
to connect to Modoboa. Learn the content and destroy
|
||||
the document as soon as possible.
|
||||
""") % account.fullname, styles["Normal"]))
|
||||
story.append(Spacer(1, 0.2 * cm))
|
||||
story.append(Paragraph(_("Web panel:"), styles["h3"]))
|
||||
data = [
|
||||
["URL", conf["webpanel_url"]],
|
||||
[_("Username"), account.username],
|
||||
[_("Password"), password]
|
||||
]
|
||||
table = Table(data)
|
||||
table.setStyle(TableStyle([
|
||||
('TEXTCOLOR', (1, 0), (1, 0), colors.blue),
|
||||
('GRID', (0, 0), (-1, -1), 1, colors.black),
|
||||
('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
|
||||
]))
|
||||
story.append(table)
|
||||
story.append(Spacer(1, 0.5 * cm))
|
||||
story.append(Paragraph(_("""
|
||||
Here you can view your emails anytime online, create filters or manage
|
||||
your contacts.
|
||||
"""), styles["Normal"]))
|
||||
|
||||
story.append(Spacer(1, 0.2 * cm))
|
||||
story.append(Paragraph(
|
||||
_("Please change your password!"),
|
||||
styles["Warning"]))
|
||||
|
||||
if conf["include_connection_settings"]:
|
||||
story.append(Spacer(1, 1 * cm))
|
||||
story.append(Paragraph(
|
||||
_("PC/Tablet/Smartphone configuration:"), styles["h3"]))
|
||||
story.append(Spacer(1, 0.2 * cm))
|
||||
data = [
|
||||
[_("SMTP server address"), conf["smtp_server_address"]],
|
||||
[_("SMTP server port"), conf["smtp_server_port"]],
|
||||
[_("SMTP connection security"), conf["smtp_connection_security"]],
|
||||
[_("IMAP server address"), conf["imap_server_address"]],
|
||||
[_("IMAP server port"), conf["imap_server_port"]],
|
||||
[_("IMAP connection security"), conf["imap_connection_security"]],
|
||||
]
|
||||
table = Table(data)
|
||||
table.setStyle(TableStyle([
|
||||
('GRID', (0, 0), (-1, -1), 1, colors.black),
|
||||
('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
|
||||
]))
|
||||
story.append(table)
|
||||
story.append(Spacer(1, 0.5 * cm))
|
||||
story.append(Paragraph(
|
||||
_("Use those settings for your computer, tablet or phone."),
|
||||
styles["Normal"])
|
||||
)
|
||||
|
||||
if conf["custom_message"]:
|
||||
story.append(Spacer(1, 2 * cm))
|
||||
story.append(Paragraph(conf["custom_message"], styles["Greeting"]))
|
||||
|
||||
doc.build(story, onFirstPage=page_template, onLaterPages=page_template)
|
||||
length = len(buff.getvalue())
|
||||
buff.seek(0)
|
||||
lib.crypt_and_save_to_file(buff, filename, length)
|
||||
@@ -0,0 +1,146 @@
|
||||
"""PDF credentials forms."""
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from django.contrib.sites import models as sites_models
|
||||
|
||||
from modoboa.lib import form_utils
|
||||
from modoboa.parameters import forms as param_forms
|
||||
|
||||
from . import constants
|
||||
|
||||
|
||||
class ParametersForm(param_forms.AdminParametersForm):
|
||||
"""Admin parameters form."""
|
||||
|
||||
app = "pdfcredentials"
|
||||
|
||||
docstore = form_utils.SeparatorField(label=_("Documents storage"))
|
||||
|
||||
storage_dir = forms.CharField(
|
||||
label=_("Directory to save documents into"),
|
||||
initial="/var/lib/modoboa/pdf_credentials",
|
||||
help_text=_("Path to a directory where PDF documents will be saved"),
|
||||
)
|
||||
|
||||
security = form_utils.SeparatorField(label=_("Security options"))
|
||||
|
||||
delete_first_dl = form_utils.YesNoField(
|
||||
label=_("Delete documents after the first download"),
|
||||
initial=True,
|
||||
help_text=_(
|
||||
"Automatically delete a document just after its first download "
|
||||
"from this interface"
|
||||
)
|
||||
)
|
||||
|
||||
generate_at_creation = form_utils.YesNoField(
|
||||
label=_("Generate documents only at account creation"),
|
||||
initial=True,
|
||||
help_text=_(
|
||||
"Generate a new document only when a new account is created. "
|
||||
"If set to no, a new document will be created each time a "
|
||||
"password is updated."
|
||||
)
|
||||
)
|
||||
|
||||
customization = form_utils.SeparatorField(label=_("Customization options"))
|
||||
|
||||
title = forms.CharField(
|
||||
label=_("Title"),
|
||||
initial=_("Personal account information"),
|
||||
help_text=_("The document's title")
|
||||
)
|
||||
|
||||
webpanel_url = forms.URLField(
|
||||
label=_("Web panel url"),
|
||||
help_text=_("URL of the Modoboa web panel")
|
||||
)
|
||||
|
||||
custom_message = forms.CharField(
|
||||
label=_("Custom message"),
|
||||
help_text=_(
|
||||
"A custom message that will appear at the end of documents"),
|
||||
required=False
|
||||
)
|
||||
|
||||
include_connection_settings = form_utils.YesNoField(
|
||||
label=_("Include mail client connection settings"),
|
||||
initial=False,
|
||||
help_text=_(
|
||||
"Include required SMTP and IMAP connection information to "
|
||||
"configure a mail client, a tablet or a phone"
|
||||
)
|
||||
)
|
||||
|
||||
smtp_server_address = forms.CharField(
|
||||
label=_("SMTP server address"),
|
||||
help_text=_("Address of the SMTP server (hostname or IP)")
|
||||
)
|
||||
|
||||
smtp_server_port = forms.IntegerField(
|
||||
label=_("SMTP server port"),
|
||||
initial=587,
|
||||
help_text=_("Listening port of the SMTP server")
|
||||
)
|
||||
|
||||
smtp_connection_security = forms.ChoiceField(
|
||||
label=_("SMTP connection security"),
|
||||
choices=constants.CONNECTION_SECURITY_MODES,
|
||||
initial="starttls",
|
||||
help_text=_("Connection security mechanism")
|
||||
)
|
||||
|
||||
imap_server_address = forms.CharField(
|
||||
label=_("IMAP server address"),
|
||||
help_text=_("Address of the IMAP server (hostname or IP)")
|
||||
)
|
||||
|
||||
imap_server_port = forms.IntegerField(
|
||||
label=_("IMAP server port"),
|
||||
initial=143,
|
||||
help_text=_("Listening port of the IMAP server")
|
||||
)
|
||||
|
||||
imap_connection_security = forms.ChoiceField(
|
||||
label=_("IMAP connection security"),
|
||||
choices=constants.CONNECTION_SECURITY_MODES,
|
||||
initial="starttls",
|
||||
help_text=_("Connection security mechanism")
|
||||
)
|
||||
|
||||
visibility_rules = {
|
||||
"smtp_server_address": "include_connection_settings=True",
|
||||
"smtp_server_port": "include_connection_settings=True",
|
||||
"smtp_connection_security": "include_connection_settings=True",
|
||||
"imap_server_address": "include_connection_settings=True",
|
||||
"imap_server_port": "include_connection_settings=True",
|
||||
"imap_connection_security": "include_connection_settings=True",
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def hostname(self):
|
||||
"""Return local hostname."""
|
||||
return sites_models.Site.objects.get_current().domain
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Set initial values."""
|
||||
super(ParametersForm, self).__init__(*args, **kwargs)
|
||||
if not self.fields["webpanel_url"].initial:
|
||||
url = "https://{}{}".format(self.hostname, settings.LOGIN_URL)
|
||||
self.fields["webpanel_url"].initial = url
|
||||
if not self.fields["smtp_server_address"].initial:
|
||||
self.fields["smtp_server_address"].initial = self.hostname
|
||||
if not self.fields["imap_server_address"].initial:
|
||||
self.fields["imap_server_address"].initial = self.hostname
|
||||
|
||||
|
||||
def load_settings():
|
||||
"""Load app settings."""
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", ParametersForm, _("PDF credentials"))
|
||||
@@ -0,0 +1,53 @@
|
||||
"""PDF credentials handlers."""
|
||||
|
||||
import os
|
||||
|
||||
from django.urls import reverse
|
||||
from django.db.models import signals
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from .documents import credentials
|
||||
from .lib import init_storage_dir, delete_credentials, get_creds_filename
|
||||
|
||||
|
||||
@receiver(core_signals.account_password_updated)
|
||||
def password_updated(sender, account, password, created, **kwargs):
|
||||
"""Create or update document."""
|
||||
if not param_tools.get_global_parameter("enabled_pdfcredentials"):
|
||||
return
|
||||
generate_at_creation = param_tools.get_global_parameter(
|
||||
"generate_at_creation")
|
||||
if (generate_at_creation and not created) or account.is_superuser:
|
||||
return
|
||||
init_storage_dir()
|
||||
credentials(account, password)
|
||||
|
||||
|
||||
@receiver(signals.pre_delete, sender=core_models.User)
|
||||
def account_deleted(sender, instance, **kwargs):
|
||||
"""Remove document."""
|
||||
delete_credentials(instance)
|
||||
|
||||
|
||||
@receiver(core_signals.extra_account_actions)
|
||||
def extra_account_actions(sender, account, **kwargs):
|
||||
"""Add link to download document."""
|
||||
if not param_tools.get_global_parameter("enabled_pdfcredentials"):
|
||||
return []
|
||||
fname = get_creds_filename(account)
|
||||
if not os.path.exists(fname):
|
||||
return []
|
||||
return [{
|
||||
"name": "get_credentials",
|
||||
"url": reverse("pdfcredentials:account_credentials",
|
||||
args=[account.id]),
|
||||
"img": "fa fa-download",
|
||||
"title": _("Retrieve user's credentials as a PDF document")
|
||||
}]
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
"""Internal library."""
|
||||
|
||||
from io import BytesIO
|
||||
import os
|
||||
import struct
|
||||
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_bytes, smart_bytes
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.lib.exceptions import InternalError
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
|
||||
def init_storage_dir():
|
||||
"""Create the directory whare documents will be stored."""
|
||||
storage_dir = param_tools.get_global_parameter("storage_dir")
|
||||
if os.path.exists(storage_dir):
|
||||
return
|
||||
try:
|
||||
os.mkdir(storage_dir)
|
||||
except (OSError, IOError) as inst:
|
||||
raise InternalError(
|
||||
_("Failed to create the directory that will contain "
|
||||
"PDF documents (%s)") % inst
|
||||
)
|
||||
|
||||
|
||||
def get_creds_filename(account):
|
||||
"""Return the full path of a document."""
|
||||
storage_dir = param_tools.get_global_parameter("storage_dir")
|
||||
return os.path.join(storage_dir, account.username + ".pdf")
|
||||
|
||||
|
||||
def delete_credentials(account):
|
||||
"""Try to delete a local file."""
|
||||
fname = get_creds_filename(account)
|
||||
if not os.path.exists(fname):
|
||||
return
|
||||
os.remove(fname)
|
||||
|
||||
|
||||
def _get_cipher(iv):
|
||||
"""Return ready-to-user Cipher."""
|
||||
key = smart_bytes(settings.SECRET_KEY[:32])
|
||||
backend = default_backend()
|
||||
return Cipher(
|
||||
algorithms.AES(force_bytes(key)),
|
||||
modes.CBC(iv),
|
||||
backend=backend
|
||||
)
|
||||
|
||||
|
||||
def crypt_and_save_to_file(content, filename, length, chunksize=64*512):
|
||||
"""Crypt content and save it to a file."""
|
||||
iv = os.urandom(16)
|
||||
cipher = _get_cipher(iv)
|
||||
encryptor = cipher.encryptor()
|
||||
with open(filename, "wb") as fp:
|
||||
fp.write(struct.pack(b"<Q", length))
|
||||
fp.write(iv)
|
||||
while True:
|
||||
chunk = content.read(chunksize)
|
||||
if not len(chunk):
|
||||
break
|
||||
elif len(chunk) % 16:
|
||||
chunk += b" " * (16 - len(chunk) % 16)
|
||||
fp.write(encryptor.update(force_bytes(chunk)))
|
||||
fp.write(encryptor.finalize())
|
||||
|
||||
|
||||
def decrypt_file(filename, chunksize=24*1024):
|
||||
"""Decrypt the content of a file and return it."""
|
||||
buff = BytesIO()
|
||||
with open(filename, "rb") as fp:
|
||||
origsize = struct.unpack(b"<Q", fp.read(struct.calcsize(b"Q")))[0]
|
||||
iv = fp.read(16)
|
||||
cipher = _get_cipher(iv)
|
||||
decryptor = cipher.decryptor()
|
||||
while True:
|
||||
chunk = fp.read(chunksize)
|
||||
if not len(chunk):
|
||||
break
|
||||
buff.write(decryptor.update(chunk))
|
||||
buff.write(decryptor.finalize())
|
||||
buff.truncate(origsize)
|
||||
return buff.getvalue()
|
||||
|
||||
|
||||
def get_document_logo():
|
||||
"""Retrieve path to logo."""
|
||||
try:
|
||||
logo = settings.MODOBOA_CUSTOM_LOGO
|
||||
logo = os.path.join(settings.MEDIA_ROOT, os.path.basename(logo))
|
||||
except AttributeError:
|
||||
logo = os.path.join(settings.STATIC_ROOT, "css/modoboa.png")
|
||||
finally:
|
||||
return logo
|
||||
@@ -0,0 +1,211 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Peter Sveter, 2016
|
||||
# Jarda Tesar <intossh@gmail.com>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2018-08-10 11:24+0000\n"
|
||||
"Last-Translator: Jarda Tesar <intossh@gmail.com>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/tonio/modoboa/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: cs_CZ\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr "Žádné"
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Informace osobního účtu"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Běží na Modoboa - Poštovní hosting zjednodušeně"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nVážený %s, tento dokument obsahuje přístupové údaje potřebné\npro pripojení do rozhraní Modoboa. Zapamatujte si je a smazte\ntento dokument hned, jakmile to bude možné.\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Webový panel:"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Uživatelské jméno"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Heslo"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nZde si kdykoliv můžete prohlédnout své emaily, vytvořit filtry nebo spravovat Vaše kontakty.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Prosím změňte si své heslo!"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "Nastavení PC/Tabletu/Smartphonu:"
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "Adresa SMTP serveru"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "Port SMTP serveru"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "Zabezpečení SMTP připojení"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "Adresa IMAP serveru"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "Port IMAP serveru"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "Zabezpečení IMAP připojení"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Použijte tato nastavení ve svém počítači, tabletu či telefonu."
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Úložný prostor pro dokumenty"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Adresář pro uložení dokumentů"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Cesta k adresáři kde budou uloženy PDF dokumenty"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Možnosti zabezpečení"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Smazat dokumenty po prvním stažení"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Automaticky smazat dokument ihned po prvním stažení cez toto rozhraní"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Vytvářet dokumenty pouze při vytváření účtu"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Vytvářet nové dokumenty pouze při vytvoření účtu. Je-li nastaveno na hodnotu ne, bude nový dokument vytvořen pokaždé, když dojde ke změne hesla."
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Možnosti vlastních úprav"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Název"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Název dokumentu"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "URL web panelu"
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL adresa Modoboa web panelu"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Vlastní zpráva"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Vlastní zpráva, která se zobrazí na konci dokumentu."
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr "Zahrnout nastavení mailového klienta"
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr "Zahrnout vyžadovaná nastavení SMTP a IMAP připojení pri konfiguraci mailového klienta, tabletu či telefonu"
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr "Adresa SMTP serveru (hostname nebo IP)"
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr "Port SMTP serveru"
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr "Zabezpečení připojení"
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr "Adresa IMAP serveru (hostname nebo IP)"
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr "Port IMAP serveru"
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Získat přístupové údaje uživatele ako PDF dokument"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Vytváření adresáře pro uložení PDF dokumentů (%s) selhalo "
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "PDF přístupové údaje"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Vytvářet PDF dokumenty obsahující přístupové údaje uživatele"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Pro tohoto uživatele není k dispozici žáden dokument"
|
||||
@@ -0,0 +1,212 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Boris Andratzek <BAndratzek@LBV-net.de>, 2018
|
||||
# Christian Wiegand, 2017
|
||||
# controlcde, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2018-04-25 14:19+0000\n"
|
||||
"Last-Translator: Boris Andratzek <BAndratzek@LBV-net.de>\n"
|
||||
"Language-Team: German (http://www.transifex.com/tonio/modoboa/language/de/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: de\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr "kein"
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Persönliche Kontoinformationen"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Powered by Modoboa - Mail hosting made simple"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nLiebe/r %s, dieses Dokument enthält die Anmeldeinformationen, die Du benötigst um Dich mit Modoboa zu verbinden. Präge Dir bitte die Informationen ein und lösche anschliessend dieses Dokument.\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Webanwendung:"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Benutzername"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Passwort"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nHier können Sie Ihre Emails online ansehen, Filter oder Kontakte erstellen.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Bitte ändern Sie Ihr Passwort!"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "PC/Tablet/Smartphone Konfiguration:"
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "SMTP Serveradresse"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "SMTP Server-Port"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "SMTP-Verbindungssicherheit"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "IMAP Serveradresse"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "IMAP Server-Port"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "IMAP Verbindungssicherheit"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Verwenden Sie diese Einstellungen für Ihren Computer, Ihr Tablet oder Telefon"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Dokumentenablage"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Speicherpfad für Dokumente"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Dateipfad in dem die PDF-Dokumente abgelegt werden"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Sicherheitseinstellungen"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Lösche Dokumente nach dem ersten Download"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Löscht automatisch das Dokument, wenn es das erste Mal über dieses Oberfläche heruntergeladen wurde"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Erzeuge Dokumente nur wenn ein Konto angelegt wurde"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Erzeuge ein neues Dokument nur wenn ein neues Konto erstellt wurde. Wenn die Option auf Nein steht wird jedes Mal ein neues Dokument erstellt, wenn ein Passwort aktualisiert wurde."
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Individuell angepasste Optionen"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Titel des Dokuments"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "URL der Webanwendung"
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL der Modoboa Webanwendung"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Eigener Nachrichtentext"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Eine eigene Nachricht, die am Ende des Dokuments angezeigt wird"
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr "Verbindungseinstellungen für Mailprogramme einschließen"
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr "Erforderliche SMTP und IMAP Einstellungen zur Konfiguration von Mailprogramme, Tablets oder Telefonen"
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr "Adresse des SMTP-Servers (Hostname oder IP)"
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr "Port, auf dem der SMTP-Server erreicht werden kann"
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr "Mechanismus zur Verbindungssicherung"
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr "Adresse des IMAP-Servers (Hostname oder IP)"
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr "Port, auf dem der IMAP-Servier erreicht werden kann"
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Erhalte die Anmeldeinformationen des Benutzer als ein PDF-Dokument"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Ein Fehler ist bei der Erstellung des Pfades, der die PDF Dokumente (%s) enthält, aufgetreten. "
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "PDF Anmeldeinformationen"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Erzeuge PDF-Dokumente welche die Benutzeranmeldeinformationen enthält"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Kein Dokument für diesen Benutzer verfügbar"
|
||||
@@ -0,0 +1,211 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Giannis Kapetanakis <bilias@edu.physics.uoc.gr>, 2016
|
||||
# Kostas Moumouris <moumouriskostas@gmail.com>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2017-10-12 13:30+0000\n"
|
||||
"Last-Translator: Kostas Moumouris <moumouriskostas@gmail.com>\n"
|
||||
"Language-Team: Greek (Greece) (http://www.transifex.com/tonio/modoboa/language/el_GR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: el_GR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr "Κανένας"
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Προσωπικές πληροφορίες λογαριασμού"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Powered by Modoboa - Mail hosting made simple"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nΑγαπητέ/ή %s, αυτό το έγγραφο περιέχει τα διαπιστευτήρια\nπου χρειάζεστε για να συνδεθείτε με το Modoboa.\nΑποστηθίστε το περιεχόμενο και διαγράψτε το έγγραφο\nτο συντομότερο δυνατόν.\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Web panel:"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Όνομα Χρήστη"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Κωδικός"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nΕδώ μπορείτε να προβάλετε τα ηλεκτρονικά σας μηνύματα σε πραγματικό χρόνο, να δημιουργήσετε φίλτρα ή να διαχειριστείτε\n τις επαφές σας.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Παρακαλώ αλλάξτε το κωδικό σας!"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "Ρυθμίσεις: PC/Tablet/Smartphone "
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "Διεύθυνση SMTP Server"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "Θύρα SMTP server"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "Ασφάλεια σύνδεσης SMTP"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "Διεύθυνση IMAP server"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "θύρα IMAP Server"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "Ασφάλεια σύνδεσης IMAP"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Χρησιμοποιήστε αυτές τις ρυθμίσεις για τον υπολογιστή, το tablet ή το τηλέφωνό σας."
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Αποθηκευτικός χώρος εγγράφων"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Κατάλογος αρχείων για την αποθήκευση εγγράφων"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Κατάλογος αρχείων για την αποθήκευση PDF εγγράφων"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Ρυθμίσεις Ασφαλείας"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Διαγραφή εγγράφων μετά την πρώτη λήψη"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Αυτόματη διαγραφή εγγράφου μετά την πρώτη λήψη από αυτήν την διεπαφή"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Δημιουργία εγγράφων μόνο κατά την δημιουργία λογαριασμού"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Δημιουργία νέου εγγράφου μόνο κατά την δημιουργία νέου λογαριασμού. Εάν επιλέξετε όχι, ένα νέο έγγραφο θα δημιουργείται κάθε φορά που ο κωδικός χρήστη ενημερώνεται."
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Επιλογές προσαρμογής"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Τίτλος"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Ο τίτλος του εγγράφου"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "Διεύθυνση Web panel"
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL του Modoboa web panel"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Προσαρμοσμένο μήνυμα"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Ένα προσαρμοσμένο μήνυμα που θα εμφανιστεί στο τέλος των εγγράφων"
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr "Συμπεριλάβε τις ρυθμίσεις σύνδεσης προγράμματος αλληλογραφίας"
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr "Συμπεριέλαβε της απαιτούμενες ρυθμίσης SMTP και IMAP για διασύνδεση με προγράμματα emai, τάμπλετ και τηλέφωνα"
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr "Διεύθυνση από τον SMTP server (hostname ή IP)"
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr "Οι θύρες που ακούει ό SMTP Server"
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr "Μηχανισμός ασφαλείας σύνδεσης"
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr "Διεύθυνση του IMAP server (hostname ή IP)"
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr "Η θύρα που ακούει ο IMAP Server"
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Ανάκτηση διαπιστευτηρίων χρήστη σε αρχείο PDF"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Σφάλμα στην δημιουργία του καταλόγου αρχείων για την αποθήκευση PDF εγγράφων (%s)"
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "Διαπιστευτήρια PDF"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Δημιουργία PDF εγγράφων που να περιέχουν τα διαπιστευτήρια χρηστών"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Δεν υπάρχουν διαθέσιμα έγγραφα για αυτόν τον χρήστη"
|
||||
@@ -0,0 +1,209 @@
|
||||
# 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: 2017-09-27 12:01+0200\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"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr ""
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,210 @@
|
||||
# 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>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2017-10-16 18:51+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: French (http://www.transifex.com/tonio/modoboa/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr "Aucune"
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Informations de compte personnel"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Propulsé par Modoboa - L'hébergement mail simplifié"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nCher %s, ce document contient les identifiants dont vous aurez\nbesoin pour vous connecter à Modoboa. Apprenez les puis détruisez\nce document le plus rapidement possible.\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Console web :"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Nom d'utilisateur"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nD'ici vous pouvez consulter vos emails en ligne n'importe quand, créer des filtres ou gérer vos contacts.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Merci de changer votre mot de passe !"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "Configuration PC/Tablette/Smartphone :"
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "Adresse du serveur SMTP"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "Port du serveur SMTP"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "Sécurité de la connexion SMTP"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "Adresse du serveur IMAP"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "Port du serveur IMAP"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "Sécurité de la connexion IMAP"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Utilisez ces paramètres pour votre ordinateur, votre tablette ou votre téléphone."
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Stockage des documents"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Répertoire dans lequel les documents sont sauvegardés"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Chemin d'accès vers le répertoire ou seront stockés les documents"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Options de sécurité"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Supprimer les documents après le premier téléchargement"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Supprimer automatiquement un document juste après son premier téléchargement depuis cette interface"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Générer les documents à la création des comptes uniquement"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Génère un nouveau document uniquement lors de la création d'un compte. Si défini à non, un nouveau document sera généré chaque fois qu'un mot de passe est changé."
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Options de personnalisation"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Titre"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Le titre du document"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "URL de la console web"
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL de la console web Modoboa"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Message personnalisé"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Un message personnalisé qui apparaîtra en bas des documents."
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr "Inclure les paramètres de connexion pour client mail"
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr "Inclure les paramètres de connexion nécessaires pour configurer un client mail, une tablette ou un téléphone"
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr "Adresse du serveur SMTP (nom d'hôte ou IP)"
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr "Port d'écoute du serveur SMTP"
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr "Mécanisme de sécurisation de la connexion"
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr "Adresse du serveur IMAP (nom d'hôte ou IP)"
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr "Port d'écoute du serveur IMAP"
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Récupérer les identifiant de l'utilisateur sous forme d'un document PDF"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Echec lors de la création du répertoire qui contiendra les documents PDF (%s)"
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "Identifiants en PDF"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Génère des documents PDF contenant les identifiants des utilisateurs"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Aucun document disponible pour cet utilisateur"
|
||||
@@ -0,0 +1,211 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# marcotrevisan <mrctrevisan@yahoo.it>, 2018
|
||||
# Rocco <mors10@hotmail.com>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2018-11-02 15:15+0000\n"
|
||||
"Last-Translator: marcotrevisan <mrctrevisan@yahoo.it>\n"
|
||||
"Language-Team: Italian (http://www.transifex.com/tonio/modoboa/language/it/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: it\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr "Nessun valore"
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Informazioni Personali"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Powered by Modoboa - Mail hosting made simple"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nGentile %s, questo documento contiene le credenziali di accesso \nper accedere a Modoboa. Leggilo e elimina\n il documento il prima possibile.\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Pannello web:"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Nome Utente"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nQui puoi sempre visualizzare le tue email onlime, creare filtri\no gestire i tuoi contatti.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Per favore cambia la tua password!"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "Configurazione PC/Tablet/Smartphone:"
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "Indirizzo del server SMTP"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "Porta del server SMTP"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "Sicurezza della connessione al server SMTP"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "indirizzo del server IMAP"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "Porta del server IMAP"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "Sicurezza della connessione al server IMAP"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Utilizza quelle impostazioni per il tuo computer, tablet o telefono."
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Memorizzazione Documenti"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Cartella nella quale salvare i documenti"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Indirizzo della cartella dove i documenti PDF saranno salvati"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Opzioni di sicurezza"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Cancella i documenti dopo averli scaricati"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Elimina automaticamente il documento dopo che è stato scaricato da questa interfaccia"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Genera documenti solo dopo la creazione dell'account"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Generare un nuovo documento solo quando si crea un nuovo account. Se impostato su no , un nuovo documento verrà creato ogni volta che la password viene aggiornata."
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Opzioni di personalizzazione"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Titolo"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Il titolo del documento"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "URL del pannello di controllo web"
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL del pannello di controllo web di Modoboa"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Messaggio personalizzato"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Un messaggio personalizzato comparirà alla fine dei documenti"
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr "Includi le impostazioni di connessione del client di posta"
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr "Includi le informazioni di connessione SMTP e IMAP richieste per configurare un client di posta, un tablet o telefono"
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr "Indirizzo del server SMTP (nome host o indirizzo IP)"
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr "Porta di ascolto del server SMTP"
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr "Meccanismo di sicurezza della connessione"
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr "Indirizzo del server IMAP (nome host o indirizzo IP)"
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr "Porta di ascolto del server IMAP"
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Recuperare le credenziali dell'utente come documento PDF"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Impossibile creare la cartella che conterrà i documenti PDF (%s)"
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "Credenziali PDF"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Genera i documenti PDF con le credenziali dell'utente"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Non ci sono documenti disponibili er questo utente"
|
||||
@@ -0,0 +1,210 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# cwatanab <chihiro.watanabe@live.jp>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2017-09-27 10:02+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Japanese (Japan) (http://www.transifex.com/tonio/modoboa/language/ja_JP/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ja_JP\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "個人アカウント情報"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Powered by Modoboa - メールホスティングをシンプルに"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\n%s さん\n\nこのドキュメントには、Modoboa へ接続するための必要な認証情報が書かれています。\n内容を理解したら、すみやかに廃棄してください。\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "ユーザ名"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "パスワード"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "ドキュメントストレージ"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "ドキュメントを保存するためのディレクトリ"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "PDF ドキュメントを保存するためのディレクトリのパス"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "セキュリティオプション"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "最初のダウンロードの後にドキュメントを削除する"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "このインターフェースから最初にダウンロードされたあとにドキュメントを自動的に削除する"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "アカウントを作成するときだけドキュメントを生成する"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "アカウントの作成されたときだけ、新しいドキュメントを生成します。\nもし「いいえ」設定すれば、新しい文書は、パスワードが更新されるたびに作成されます。"
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "PDF ドキュメントとしてユーザー認証情報を取得します"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "PDFドキュメントを格納するディレクトリの作成に失敗しました (%s)"
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "PDF 認証情報"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "ユーザーの認証情報を書かれた PDF ドキュメントを生成"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "このユーザーにはドキュメンがありません"
|
||||
@@ -0,0 +1,211 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# R Kloosterman <randx@zeelandnet.nl>, 2016
|
||||
# Tuxis Internet Engineering V.O.F. <info@tuxis.nl>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2018-01-31 08:43+0000\n"
|
||||
"Last-Translator: Tuxis Internet Engineering V.O.F. <info@tuxis.nl>\n"
|
||||
"Language-Team: Dutch (Netherlands) (http://www.transifex.com/tonio/modoboa/language/nl_NL/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: nl_NL\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Persoonlijke account informatie"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Aangeboden door Modoboa - Mail hosting made simple"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nBeste %s, dit document bevat alle gegevens dat u nodig\nheeft voor het gebruiken van Modoboa. Onthoud deze gegevens\nen verwijder dit document zo snel mogelijk.\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Webpaneel:"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Gebruikersnaam"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Wachtwoord"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nHier kunt u uw e-mails online bekijken, filters aanmaken, of contactpersonen beheren.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Wijzig uw wachtwoord aub!"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "PC/Tablet/Smartphone configuratie:"
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "SMTP serveradres"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "SMTP server poort"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "SMTP verbinding beveiliging"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "IMAP serveradres"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "IMAP server poort"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "IMAP verbinding beveiliging"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Gebruik deze instellingen voor uw computer, tablet of telefoon."
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Document opslag"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Map voor het opslaan van de documenten"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Pad naar de map waar de PDF documenten worden opgeslagen"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Beveiligings-opties"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Documenten verwijderen na eerste download"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Verwijder een document automatisch nadat het eenmalig is gedownload van paneel"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Genereer een document enkel bij het aanmaken van een account"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Genereer een document enkel wanneer een account is nieuw aangemaakt. Indien 'nee' is geselecteerd zal bij iedere wachtwoord wijziging een nieuw document worden gemaakt. "
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Personaliseringsopties"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Titel van het document"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "Webpaneel URL"
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL van het Modoboa webpaneel"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Aangepast bericht"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Een aangepast bericht dat aan het einde van de documenten komt te staan"
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Vraag de gebruikers gegevens op als een PDF document"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Het aanmaken van de map voor de PDF documenten is mislukt (%s)"
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "PDF gegevens"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Genereer PDF document met de gegevens voor de gebruiker"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Geen document beschikbaar voor deze gebruiker"
|
||||
@@ -0,0 +1,211 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# sin88 <sin@sin.waw.pl>, 2016
|
||||
# Tomasz Proć <tomasz.proc@gmail.com>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2017-12-02 10:36+0000\n"
|
||||
"Last-Translator: Tomasz Proć <tomasz.proc@gmail.com>\n"
|
||||
"Language-Team: Polish (Poland) (http://www.transifex.com/tonio/modoboa/language/pl_PL/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pl_PL\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr "Brak"
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Informacje o koncie osobistym"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Powered by Modoboa - Mail hosting made simple"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nDrogi użytkowniku %s, ten dokument zawiera dane uwierzytelniające które będzeisz potrzebował to połączenia się. Zapoznaj się z nim i usuń go najszybciej jak to możliwe.\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Panel web:"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Nazwa użytkownika"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Hasło"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nPod tym adresem możesz online przeczytać swoje wiadomości, stworzyć filtry lub zarządzać\n listą kontaktów.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Proszę zmienić swoje hasło!"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "konfiguracją PC/Tabletu/Smartfonu:"
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "Adres serwera SMTP"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "Port serwera SMTP"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "Zabezpieczenia połączenia SMTP"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "Adres serwera IMAP"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "Port serwera IMAP"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "Zabezpieczenie połączenia IMAP"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Użyj tych ustawień w swoim komputerze, tablecie lub telefonie."
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Magazyn dokumentów"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Lokalizacja gdzie zapisywać dokumenty"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Ścieżka do lokalizacji, gdzie będą zapisywane PDF'y"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Opcje bezpieczeństwa"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Usuwaj dokumenty po ich pierwszym pobraniu"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Automatycznie usuwaj dokumenty jak tylko zostaną pobranie przez ten interfejs"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Generuj dokumenty tylko podczas zakładania konta"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Generuj nowy dokument tylko wtedy, kiedy nowe konto jest zakładane. Jeśli ustawione na nie, to nowy dokument będzie tworzony przy każdej zmianie hasła."
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Opcje dostosowania"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Tytuł"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Tytuł dokumentu"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "URL panelu Web"
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL panelu Modoboa"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Własna wiadomość"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Dodatkowa wiadomość która pojawi się na końcu dokumentu."
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr "Załącz ustawienia połączenia dla programu pocztowego klienta"
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr "Załącz wymagane do konfiguracji, informacje o połączeniu SMTP i IMAP "
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr "Adres serwera SMTP (nazwa hosta lub IP)"
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr "Port nasłuchujący serwera SMTP"
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr "Mechanizm zabezpieczenia połączenia"
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr "Adres serwera IMAP (nazwa hosta lub IP)"
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr "Port nasłuchujący serwera IMAP"
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Pobieranie danych uwierzytelniających użytkownika w formacie PDF"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Nie można utworzyć katalogu do przechowywania PDF'ów (%s)"
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "Poświadczenia PDF"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Generuj dokumenty PDF zawierające dane uwierzytelniające użytkowników"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Brak dokumentu dla tego użytkownika"
|
||||
@@ -0,0 +1,211 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Rafael Barretto <ch3yd@hotmail.com>, 2015
|
||||
# Rafael Barretto <ch3yd@hotmail.com>, 2017-2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2018-09-25 03:25+0000\n"
|
||||
"Last-Translator: Rafael Barretto <ch3yd@hotmail.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/tonio/modoboa/language/pt_BR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pt_BR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr "Nenhuma"
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Informações da conta pessoal"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Desenvolvido por Modoboa - Hospedagem de email de forma simples"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nCaro(a) %s, este documento contem as credenciais que você irá precisar\npara conectar ao Modoboa. Verifique o conteúdo e destrua\neste documento assim que possível.\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Painel web:"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Nome de usuário"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Senha"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nAqui você poderá ver seus emails a qualquer momento online, crie filtros ou gerencie \nseus contatos.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Por favor mude sua senha!"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "Configuração para PC/Tablet/Smartphone:"
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "Endereço do servidor SMTP"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "Porta do servidor SMTP"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "Conexão segura SMTP"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "Endereço do servidor IMAP"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "Porta do servidor IMAP"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "Conexão segura IMAP"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Use essas configurações para seu computador, tablet ou telefone."
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Armazenamento de documentos"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Diretório para salvar documentos"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Caminho para o diretório onde os arquivos PDF serão salvos"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Opções de segurança"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Deletar documentos após o primeiro download"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Excluir automaticamente um documento logo após a sua primeira transferência a partir desta interface"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Apenas gerar documentos na criação da conta"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Gerar um novo documento apenas quando uma nova conta é criada. Se definido como não, um novo documento será criado cada vez que uma senha é atualizada."
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Opções de customização"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Título"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Título do documento"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "URL do painel web"
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL do painel web do Modoboa"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Mensagem personalizada"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Uma mensagem personalizada irá aparecer no fim do documento"
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr "Incluir configurações de conexão do cliente de email"
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr "Incluir informações de conexão SMTP e IMAP necessárias para configurar um cliente de e-mail, um tablet ou um telefone"
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr "Endereço do servidor SMTP (hostname ou IP)"
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr "Mecanismo de conexão segura"
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Recuperar credenciais do usuário como um documento PDF"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Falha ao criar o diretório que conterá documentos PDF (%s)"
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "Credenciais PDF"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Gerar documentos em PDF contendo as credenciais dos usuários"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Nenhum documento disponível para esse usuário"
|
||||
@@ -0,0 +1,209 @@
|
||||
# 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: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2017-09-27 10:02+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Portuguese (Portugal) (http://www.transifex.com/tonio/modoboa/language/pt_PT/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pt_PT\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr ""
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr ""
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,211 @@
|
||||
# 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>, 2016,2018
|
||||
# Tomas Olsson <fettoemo@gmail.com>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-27 12:01+0200\n"
|
||||
"PO-Revision-Date: 2018-08-14 08:40+0000\n"
|
||||
"Last-Translator: Olle Gustafsson <olle@dalnix.se>\n"
|
||||
"Language-Team: Swedish (http://www.transifex.com/tonio/modoboa/language/sv/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: sv\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: constants.py:7
|
||||
msgid "None"
|
||||
msgstr "Ingen"
|
||||
|
||||
#: documents.py:52 forms.py:53
|
||||
msgid "Personal account information"
|
||||
msgstr "Personlig kontoinformation"
|
||||
|
||||
#: documents.py:55
|
||||
msgid "Powered by Modoboa - Mail hosting made simple"
|
||||
msgstr "Drivs av Modoboa - Mail hosting gjort enkelt"
|
||||
|
||||
#: documents.py:69
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"Dear %s, this document contains the credentials you will need\n"
|
||||
"to connect to Modoboa. Learn the content and destroy\n"
|
||||
"the document as soon as possible.\n"
|
||||
msgstr "\nKära %s, detta dokument innehåller de kontouppgifter du behöver för att ansluta till Modoboa. Lär dig innehållet i detta dokument och förstör detta dokument så snart som möjligt\n"
|
||||
|
||||
#: documents.py:75
|
||||
msgid "Web panel:"
|
||||
msgstr "Webbpanel"
|
||||
|
||||
#: documents.py:78
|
||||
msgid "Username"
|
||||
msgstr "Användarnamn"
|
||||
|
||||
#: documents.py:79
|
||||
msgid "Password"
|
||||
msgstr "Lösenord"
|
||||
|
||||
#: documents.py:89
|
||||
msgid ""
|
||||
"\n"
|
||||
"Here you can view your emails anytime online, create filters or manage\n"
|
||||
"your contacts.\n"
|
||||
msgstr "\nHär kan du se dina e-postmeddelanden när som helst online, skapa filter eller hantera\ndina kontakter.\n"
|
||||
|
||||
#: documents.py:96
|
||||
msgid "Please change your password!"
|
||||
msgstr "Vänligen ändra ditt lösenord!"
|
||||
|
||||
#: documents.py:102
|
||||
msgid "PC/Tablet/Smartphone configuration:"
|
||||
msgstr "PC/Tablet/Smartphone inställningar:"
|
||||
|
||||
#: documents.py:105 forms.py:79
|
||||
msgid "SMTP server address"
|
||||
msgstr "SMTP server adress"
|
||||
|
||||
#: documents.py:106 forms.py:84
|
||||
msgid "SMTP server port"
|
||||
msgstr "SMTP server port"
|
||||
|
||||
#: documents.py:107 forms.py:90
|
||||
msgid "SMTP connection security"
|
||||
msgstr "SMTP anslutningssäkerhet"
|
||||
|
||||
#: documents.py:108 forms.py:97
|
||||
msgid "IMAP server address"
|
||||
msgstr "IMAP server adress"
|
||||
|
||||
#: documents.py:109 forms.py:102
|
||||
msgid "IMAP server port"
|
||||
msgstr "IMAP server port"
|
||||
|
||||
#: documents.py:110 forms.py:108
|
||||
msgid "IMAP connection security"
|
||||
msgstr "IMAP anslutningssäkerhet"
|
||||
|
||||
#: documents.py:120
|
||||
msgid "Use those settings for your computer, tablet or phone."
|
||||
msgstr "Använd dessa inställningar för din dator, surfplatta eller telefon."
|
||||
|
||||
#: forms.py:20
|
||||
msgid "Documents storage"
|
||||
msgstr "Dokumentlagring"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Directory to save documents into"
|
||||
msgstr "Katalog att spara dokument till"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to a directory where PDF documents will be saved"
|
||||
msgstr "Sökväg till en katalog där PDF dokument kommer sparas"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Security options"
|
||||
msgstr "Säkerhetsinställningar"
|
||||
|
||||
#: forms.py:31
|
||||
msgid "Delete documents after the first download"
|
||||
msgstr "Radera dokument efter första nedladdning"
|
||||
|
||||
#: forms.py:34
|
||||
msgid ""
|
||||
"Automatically delete a document just after its first download from this "
|
||||
"interface"
|
||||
msgstr "Radera dokument automatiskt efter första nedladdningen"
|
||||
|
||||
#: forms.py:40
|
||||
msgid "Generate documents only at account creation"
|
||||
msgstr "Generera dokument endast vid kontoskapande"
|
||||
|
||||
#: forms.py:43
|
||||
msgid ""
|
||||
"Generate a new document only when a new account is created. If set to no, a "
|
||||
"new document will be created each time a password is updated."
|
||||
msgstr "Generera bara nya dokument när ett nytt konto skapas. Om detta sätts till nej, kommer ett nytt dokument skapas varje gång ett lösenord uppdateras."
|
||||
|
||||
#: forms.py:49
|
||||
msgid "Customization options"
|
||||
msgstr "Anpassningsalternativ"
|
||||
|
||||
#: forms.py:52
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "The document's title"
|
||||
msgstr "Dokumentets titel"
|
||||
|
||||
#: forms.py:58
|
||||
msgid "Web panel url"
|
||||
msgstr "Webbpanels länk "
|
||||
|
||||
#: forms.py:59
|
||||
msgid "URL of the Modoboa web panel"
|
||||
msgstr "URL till Modoboa webbpanel"
|
||||
|
||||
#: forms.py:63
|
||||
msgid "Custom message"
|
||||
msgstr "Anpassat meddelande"
|
||||
|
||||
#: forms.py:65
|
||||
msgid "A custom message that will appear at the end of documents"
|
||||
msgstr "Ett anpassat meddelande som kommer visas i slutet på dokumentet"
|
||||
|
||||
#: forms.py:70
|
||||
msgid "Include mail client connection settings"
|
||||
msgstr "Inkludera e-post klient inställningar"
|
||||
|
||||
#: forms.py:73
|
||||
msgid ""
|
||||
"Include required SMTP and IMAP connection information to configure a mail "
|
||||
"client, a tablet or a phone"
|
||||
msgstr "Inkludera SMTP och IMAP anslutningsinformation för att konfigurera en e-postklient, surfplatta eller telefon"
|
||||
|
||||
#: forms.py:80
|
||||
msgid "Address of the SMTP server (hostname or IP)"
|
||||
msgstr "Adress till SMTP servern (värdnamn eller IP)"
|
||||
|
||||
#: forms.py:86
|
||||
msgid "Listening port of the SMTP server"
|
||||
msgstr "Lyssningsport för SMTP servern"
|
||||
|
||||
#: forms.py:93 forms.py:111
|
||||
msgid "Connection security mechanism"
|
||||
msgstr "Anslutningssäkerhetsmekanism"
|
||||
|
||||
#: forms.py:98
|
||||
msgid "Address of the IMAP server (hostname or IP)"
|
||||
msgstr "Adress till IMAP servern (värdnamn eller IP)"
|
||||
|
||||
#: forms.py:104
|
||||
msgid "Listening port of the IMAP server"
|
||||
msgstr "Lyssningsport för IMAP servern"
|
||||
|
||||
#: handlers.py:46
|
||||
msgid "Retrieve user's credentials as a PDF document"
|
||||
msgstr "Hämta användares kontouppgifter som ett PDF dokument"
|
||||
|
||||
#: lib.py:29
|
||||
#, python-format
|
||||
msgid "Failed to create the directory that will contain PDF documents (%s)"
|
||||
msgstr "Kunde inte skapa katalogen som innehåller PDF dokumenten (%s)"
|
||||
|
||||
#: modo_extension.py:16 modo_extension.py:24
|
||||
msgid "PDF credentials"
|
||||
msgstr "PDF kontouppgifter"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Generate PDF documents containing users' credentials"
|
||||
msgstr "Generera PDF dokument innehållande användares kontouppgifter"
|
||||
|
||||
#: views.py:30
|
||||
msgid "No document available for this user"
|
||||
msgstr "Inga dokument tillgängliga för den här användaren"
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
@@ -0,0 +1,109 @@
|
||||
"""
|
||||
Copy of the original rfc6266 package, just the generation part.
|
||||
|
||||
Orginal code is available at https://github.com/g2p/rfc6266.
|
||||
"""
|
||||
|
||||
from urllib.parse import quote
|
||||
|
||||
|
||||
# RFC 2616
|
||||
separator_chars = "()<>@,;:\\\"/[]?={} \t"
|
||||
# RFC 5987
|
||||
attr_chars_nonalnum = '!#$&+-.^_`|~'
|
||||
|
||||
|
||||
def percent_encode(string, safe, encoding):
|
||||
return quote(string, safe, encoding, errors='strict')
|
||||
|
||||
|
||||
def is_token_char(ch):
|
||||
# Must be ascii, and neither a control char nor a separator char
|
||||
asciicode = ord(ch)
|
||||
# < 128 means ascii, exclude control chars at 0-31 and 127,
|
||||
# exclude separator characters.
|
||||
return 31 < asciicode < 127 and ch not in separator_chars
|
||||
|
||||
|
||||
def is_token(candidate):
|
||||
return all(is_token_char(ch) for ch in candidate)
|
||||
|
||||
|
||||
def is_ascii(text):
|
||||
return all(ord(ch) < 128 for ch in text)
|
||||
|
||||
|
||||
def fits_inside_codec(text, codec):
|
||||
try:
|
||||
text.encode(codec)
|
||||
except UnicodeEncodeError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def is_lws_safe(text):
|
||||
return normalize_ws(text) == text
|
||||
|
||||
|
||||
def normalize_ws(text):
|
||||
return ' '.join(text.split())
|
||||
|
||||
|
||||
def qd_quote(text):
|
||||
return text.replace('\\', '\\\\').replace('"', '\\"')
|
||||
|
||||
|
||||
def build_header(
|
||||
filename, disposition='attachment', filename_compat=None
|
||||
):
|
||||
"""Generate a Content-Disposition header for a given filename.
|
||||
For legacy clients that don't understand the filename* parameter,
|
||||
a filename_compat value may be given.
|
||||
It should either be ascii-only (recommended) or iso-8859-1 only.
|
||||
In the later case it should be a character string
|
||||
(unicode in Python 2).
|
||||
Options for generating filename_compat (only useful for legacy clients):
|
||||
- ignore (will only send filename*);
|
||||
- strip accents using unicode's decomposing normalisations,
|
||||
which can be done from unicode data (stdlib), and keep only ascii;
|
||||
- use the ascii transliteration tables from Unidecode (PyPI);
|
||||
- use iso-8859-1
|
||||
Ignore is the safest, and can be used to trigger a fallback
|
||||
to the document location (which can be percent-encoded utf-8
|
||||
if you control the URLs).
|
||||
See https://tools.ietf.org/html/rfc6266#appendix-D
|
||||
"""
|
||||
|
||||
# While this method exists, it could also sanitize the filename
|
||||
# by rejecting slashes or other weirdness that might upset a receiver.
|
||||
|
||||
if disposition != 'attachment':
|
||||
assert is_token(disposition)
|
||||
|
||||
rv = disposition
|
||||
|
||||
if is_token(filename):
|
||||
rv += '; filename=%s' % (filename, )
|
||||
return rv
|
||||
elif is_ascii(filename) and is_lws_safe(filename):
|
||||
qd_filename = qd_quote(filename)
|
||||
rv += '; filename="%s"' % (qd_filename, )
|
||||
if qd_filename == filename:
|
||||
# RFC 6266 claims some implementations are iffy on qdtext's
|
||||
# backslash-escaping, we'll include filename* in that case.
|
||||
return rv
|
||||
elif filename_compat:
|
||||
if is_token(filename_compat):
|
||||
rv += '; filename=%s' % (filename_compat, )
|
||||
else:
|
||||
assert is_lws_safe(filename_compat)
|
||||
rv += '; filename="%s"' % (qd_quote(filename_compat), )
|
||||
|
||||
# alnum are already considered always-safe, but the rest isn't.
|
||||
# Python encodes ~ when it shouldn't, for example.
|
||||
rv += "; filename*=utf-8''%s" % (percent_encode(
|
||||
filename, safe=attr_chars_nonalnum, encoding='utf-8'), )
|
||||
|
||||
# This will only encode filename_compat, if it used non-ascii iso-8859-1.
|
||||
return rv.encode('iso-8859-1')
|
||||
@@ -0,0 +1,147 @@
|
||||
"""PDF credentials tests."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
from django.test import override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
from modoboa.admin import factories as admin_factories
|
||||
from modoboa.core import models as core_models
|
||||
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
|
||||
class EventsTestCase(ModoTestCase):
|
||||
"""Test event handlers."""
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create some data."""
|
||||
super(EventsTestCase, cls).setUpTestData()
|
||||
admin_factories.DomainFactory(name="test.com")
|
||||
|
||||
def setUp(self):
|
||||
"""Create temp. directory to store files."""
|
||||
super(EventsTestCase, self).setUp()
|
||||
self.workdir = tempfile.mkdtemp()
|
||||
self.set_global_parameter("storage_dir", self.workdir)
|
||||
|
||||
def tearDown(self):
|
||||
"""Reset test env."""
|
||||
shutil.rmtree(self.workdir)
|
||||
|
||||
def _create_account(self, username, expected_status=200):
|
||||
"""Create a test account."""
|
||||
values = {
|
||||
"username": username,
|
||||
"first_name": "Tester", "last_name": "Toto",
|
||||
"role": "SimpleUsers", "quota_act": True,
|
||||
"is_active": True, "email": username,
|
||||
"random_password": True, "stepid": 2
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("admin:account_add"), values,
|
||||
HTTP_X_REQUESTED_WITH="XMLHttpRequest")
|
||||
self.assertEqual(response.status_code, expected_status)
|
||||
return values
|
||||
|
||||
def test_password_updated(self):
|
||||
"""Check that document is generated at account creation/update."""
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
account = core_models.User.objects.get(username=values["username"])
|
||||
|
||||
# Check if link is present in listing page
|
||||
response = self.ajax_get(reverse("admin:_identity_list"))
|
||||
self.assertIn('name="get_credentials"', response["rows"])
|
||||
|
||||
# Try to download the file
|
||||
response = self.client.get(
|
||||
reverse("pdfcredentials:account_credentials",
|
||||
args=[account.pk]))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response["Content-Type"], "application/pdf")
|
||||
|
||||
# File have been deleted?
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
# Try to download a second time
|
||||
response = self.client.get(
|
||||
reverse("pdfcredentials:account_credentials",
|
||||
args=[account.pk]))
|
||||
self.assertContains(response, "No document available for this user")
|
||||
|
||||
# Update account
|
||||
values.update({"language": "en"})
|
||||
self.ajax_post(
|
||||
reverse("admin:account_change", args=[account.pk]), values
|
||||
)
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
self.set_global_parameter("generate_at_creation", False)
|
||||
self.ajax_post(
|
||||
reverse("admin:account_change", args=[account.pk]), values
|
||||
)
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
|
||||
def test_with_connection_settings(self):
|
||||
"""Add connection settings to documents."""
|
||||
self.set_global_parameter("include_connection_settings", True)
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
|
||||
def test_with_custom_message(self):
|
||||
"""Add custom message to documents."""
|
||||
self.set_global_parameter("custom_message", "This is a test message.")
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
|
||||
def test_account_delete(self):
|
||||
"""Check that document is deleted with account."""
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
account = core_models.User.objects.get(username=values["username"])
|
||||
self.ajax_post(
|
||||
reverse("admin:account_delete", args=[account.pk]), {}
|
||||
)
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
@override_settings(MODOBOA_LOGO="modoboa.png")
|
||||
def test_with_custom_logo(self):
|
||||
"""Check that document is deleted with account."""
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
|
||||
def test_download_and_delete_account(self):
|
||||
"""Check that document is deleted with account."""
|
||||
values = self._create_account("leon@test.com")
|
||||
fname = os.path.join(self.workdir, "{}.pdf".format(values["username"]))
|
||||
self.assertTrue(os.path.exists(fname))
|
||||
account = core_models.User.objects.get(username=values["username"])
|
||||
|
||||
# Try to download the file
|
||||
response = self.client.get(
|
||||
reverse("pdfcredentials:account_credentials",
|
||||
args=[account.pk]))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response["Content-Type"], "application/pdf")
|
||||
|
||||
# File have been deleted?
|
||||
self.assertFalse(os.path.exists(fname))
|
||||
|
||||
# Delete account
|
||||
self.ajax_post(
|
||||
reverse("admin:account_delete", args=[account.pk]), {}
|
||||
)
|
||||
|
||||
def test_storage_dir_creation(self):
|
||||
"""Test storage directory creation."""
|
||||
self.set_global_parameter("storage_dir", "/nonexistentdir")
|
||||
self._create_account("leon@test.com", expected_status=500)
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = "pdfcredentials"
|
||||
|
||||
urlpatterns = [
|
||||
path('credentials/<int:accountid>/', views.get_account_credentials,
|
||||
name="account_credentials"),
|
||||
]
|
||||
@@ -0,0 +1,37 @@
|
||||
"""modoboa.pdfcredentials views."""
|
||||
|
||||
import os
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from django.contrib.auth.decorators import (
|
||||
login_required, permission_required
|
||||
)
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib.exceptions import ModoboaException, PermDeniedException
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from .lib import decrypt_file, get_creds_filename
|
||||
from .rfc6266 import build_header
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("core.add_user")
|
||||
def get_account_credentials(request, accountid):
|
||||
"""View to download a document."""
|
||||
account = User.objects.get(pk=accountid)
|
||||
if not request.user.can_access(account):
|
||||
raise PermDeniedException()
|
||||
fname = get_creds_filename(account)
|
||||
if not os.path.exists(fname):
|
||||
raise ModoboaException(_("No document available for this user"))
|
||||
content = decrypt_file(fname)
|
||||
if param_tools.get_global_parameter("delete_first_dl"):
|
||||
os.remove(fname)
|
||||
resp = HttpResponse(content)
|
||||
resp["Content-Type"] = "application/pdf"
|
||||
resp["Content-Length"] = len(content)
|
||||
resp["Content-Disposition"] = build_header(os.path.basename(fname))
|
||||
return resp
|
||||
@@ -27,6 +27,7 @@ urlpatterns = [
|
||||
path('', include("modoboa.core.urls")),
|
||||
path('admin/', include("modoboa.admin.urls")),
|
||||
path('dnstools/', include("modoboa.dnstools.urls")),
|
||||
path('pdfcredentials', include("modoboa.pdfcredentials.urls")),
|
||||
path('stats/', include("modoboa.maillog.urls")),
|
||||
|
||||
path('user/forward/', user_views.forward, name="user_forward"),
|
||||
|
||||
@@ -15,6 +15,7 @@ urlpatterns = [
|
||||
path('', include("modoboa.dnstools.api.v2.urls")),
|
||||
path('', include("modoboa.maillog.api.v2.urls")),
|
||||
path('', include("modoboa.transport.api.v2.urls")),
|
||||
path('', include("modoboa.pdfcredentials.api.v2.urls")),
|
||||
]
|
||||
|
||||
urlpatterns += exts_pool.get_urls(category="api")
|
||||
|
||||
@@ -37,3 +37,6 @@ qrcode
|
||||
|
||||
aiosmtplib
|
||||
aioredis==2.0.1
|
||||
|
||||
# PDF credentials
|
||||
reportlab
|
||||
@@ -89,6 +89,7 @@ MODOBOA_APPS = (
|
||||
'modoboa.dnstools',
|
||||
'modoboa.policyd',
|
||||
'modoboa.maillog',
|
||||
'modoboa.pdfcredentials',
|
||||
# Modoboa extensions here.
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user