From d9c934e432b6a3414f8a60f87ff1517b19973be9 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Sat, 8 Oct 2016 09:10:18 +0200 Subject: [PATCH 01/12] Updated french translation. --- modoboa/admin/locale/fr/LC_MESSAGES/django.po | 146 +++++------------- modoboa/locale/fr/LC_MESSAGES/django.po | 76 +++------ 2 files changed, 59 insertions(+), 163 deletions(-) diff --git a/modoboa/admin/locale/fr/LC_MESSAGES/django.po b/modoboa/admin/locale/fr/LC_MESSAGES/django.po index 8c0d64371..896118478 100644 --- a/modoboa/admin/locale/fr/LC_MESSAGES/django.po +++ b/modoboa/admin/locale/fr/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Antoine Nguyen , 2015-2016 msgid "" @@ -9,13 +9,13 @@ msgstr "" "Project-Id-Version: Modoboa\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-10-06 13:36+0200\n" -"PO-Revision-Date: 2016-09-16 13:56+0000\n" +"PO-Revision-Date: 2016-10-08 07:09+0000\n" "Last-Translator: Antoine Nguyen \n" "Language-Team: French (http://www.transifex.com/tonio/modoboa/language/fr/)\n" -"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: admin/app_settings.py:54 admin/callbacks.py:25 @@ -38,11 +38,9 @@ msgstr "MX(s) valide(s)" #: admin/app_settings.py:68 msgid "" -"IP(s) or network(s) of the MX that should match with domains' MX records. On " -"per line." -msgstr "" -"IP(s) ou réseau(x) avec lesquels les enregistrements MX des domaines doivent " -"correspondre. Un par ligne." +"IP(s) or network(s) of the MX that should match with domains' MX records. On" +" per line." +msgstr "IP(s) ou réseau(x) avec lesquels les enregistrements MX des domaines doivent correspondre. Un par ligne." #: admin/app_settings.py:77 msgid "Enable DNSBL checks" @@ -64,9 +62,7 @@ msgstr "Gérer les boites sur le système de fichiers" msgid "" "Rename or remove mailboxes on the filesystem when they get renamed or " "removed within Modoboa" -msgstr "" -"Renommer ou supprimer les boites sur le système de fichiers quand elles sont " -"renommées ou supprimées dans Modoboa" +msgstr "Renommer ou supprimer les boites sur le système de fichiers quand elles sont renommées ou supprimées dans Modoboa" #: admin/app_settings.py:96 msgid "Mailboxes owner" @@ -84,9 +80,7 @@ msgstr "Quota de domaine par défaut" msgid "" "Default quota (in MB) applied to freshly created domains with no value " "specified. A value of 0 means no quota." -msgstr "" -"Quota par défaut (en Mo) appliqué aux domaines fraichement créés et ne " -"spécifiant pas de valeur. 0 signifie qu'aucun quota ne sera appliqué." +msgstr "Quota par défaut (en Mo) appliqué aux domaines fraichement créés et ne spécifiant pas de valeur. 0 signifie qu'aucun quota ne sera appliqué." #: admin/app_settings.py:113 msgid "Automatic account removal" @@ -94,19 +88,16 @@ msgstr "Suppression automatique de compte" #: admin/app_settings.py:116 msgid "When a mailbox is removed, also remove the associated account" -msgstr "" -"Lorsqu'une boite aux lettres est supprimée, supprimer le compte associé en " -"même temps" +msgstr "Lorsqu'une boite aux lettres est supprimée, supprimer le compte associé en même temps" #: admin/app_settings.py:120 msgid "Automatic domain/mailbox creation" msgstr "Création automatique de domaine/boite aux lettres" #: admin/app_settings.py:123 -msgid "Create a domain and a mailbox when an account is automatically created." -msgstr "" -"Créer un domaine et une boite aux lettres quand un compte est créé " -"automatiquement." +msgid "" +"Create a domain and a mailbox when an account is automatically created." +msgstr "Créer un domaine et une boite aux lettres quand un compte est créé automatiquement." #: admin/app_settings.py:170 admin/forms/account.py:292 #: admin/forms/domain.py:81 @@ -153,9 +144,7 @@ msgstr "Nom d'utilisateur" msgid "" "The user's name. Must be a valid e-mail address for simple users or " "administrators with a mailbox." -msgstr "" -"Le nom de l'utilisateur. Doit être une adresse e-mail valide pour les " -"utilisateurs simples ou les administrateurs avec une boite aux lettres." +msgstr "Le nom de l'utilisateur. Doit être une adresse e-mail valide pour les utilisateurs simples ou les administrateurs avec une boite aux lettres." #: admin/forms/account.py:40 admin/templates/admin/account_detail.html:29 msgid "Role" @@ -211,10 +200,7 @@ msgid "" "Quota in MB for this mailbox. Define a custom value or use domain's default " "one. Leave empty to define an unlimited value (not allowed for domain " "administrators)." -msgstr "" -"Quota en Mo pour cette boite. Définir une valeur spécifique ou utiliser la " -"valeur par défaut du domaine. Laisser vide pour définir une valeur illimitée " -"(interdit pour les admins. de domaine)." +msgstr "Quota en Mo pour cette boite. Définir une valeur spécifique ou utiliser la valeur par défaut du domaine. Laisser vide pour définir une valeur illimitée (interdit pour les admins. de domaine)." #: admin/forms/account.py:205 admin/forms/domain.py:44 #: admin/templates/admin/domains.html:35 @@ -226,10 +212,7 @@ msgid "" "Alias(es) of this mailbox. Indicate only one address per input, press ENTER " "to add a new input. Use the '*' character to create a 'catchall' alias (ex: " "*@domain.tld)." -msgstr "" -"Alias de cette boite. Indiquer seulement une adresse par champ, appuyer sur " -"ENTREE pour ajouter un nouveau champ. Utiliser le caractère '*' pour créer " -"une adresse 'attrape tout' (ex: *@domain.tld)." +msgstr "Alias de cette boite. Indiquer seulement une adresse par champ, appuyer sur ENTREE pour ajouter un nouveau champ. Utiliser le caractère '*' pour créer une adresse 'attrape tout' (ex: *@domain.tld)." #: admin/forms/account.py:214 msgid "Sender addresses" @@ -240,11 +223,7 @@ msgid "" "Additional sender address(es) for this account. The user will be allowed to " "send emails using this address, even if it does not exist locally. Indicate " "one address per input. Press ENTER to add a new input." -msgstr "" -"Adresse(s) d'envoi supplémentaire(s) pour ce compte. L'utilisateur sera " -"autorisé à envoyer des e-mails en utilisant la/les adresse(s) déclarée(s), " -"même si elle(s) n'existe(nt) pas localement. Indiquer une adresse par champ. " -"Appuyer sur ENTREE pour ajouter un nouveau champ." +msgstr "Adresse(s) d'envoi supplémentaire(s) pour ce compte. L'utilisateur sera autorisé à envoyer des e-mails en utilisant la/les adresse(s) déclarée(s), même si elle(s) n'existe(nt) pas localement. Indiquer une adresse par champ. Appuyer sur ENTREE pour ajouter un nouveau champ." #: admin/forms/account.py:271 admin/forms/alias.py:92 #: admin/models/mailbox.py:293 @@ -300,9 +279,7 @@ msgstr "Adresse email" msgid "" "The alias address. To create a catchall alias, just enter the domain name " "(@domain.tld)." -msgstr "" -"L'adresse de l'alias. Pour créer un alias \"fourre-tout\", saisissez " -"uniquement le nom du domaine (@domain.tld)." +msgstr "L'adresse de l'alias. Pour créer un alias \"fourre-tout\", saisissez uniquement le nom du domaine (@domain.tld)." #: admin/forms/alias.py:35 admin/templates/admin/alias_detail.html:37 msgid "Recipients" @@ -312,9 +289,7 @@ msgstr "Destinataires" msgid "" "Addresses this alias will point to. Indicate only one address per input, " "press ENTER to add a new input." -msgstr "" -"Les adresses vers lesquelles cet alias pointera. Indiquer une adresse par " -"champ, appuyer sur ENTREE pour ajouter un nouveau champ." +msgstr "Les adresses vers lesquelles cet alias pointera. Indiquer une adresse par champ, appuyer sur ENTREE pour ajouter un nouveau champ." #: admin/forms/alias.py:47 admin/forms/domain.py:24 admin/models/domain.py:90 #: admin/templates/admin/domain_statistics.html:49 @@ -341,17 +316,13 @@ msgstr "Type" msgid "" "Default quota in MB applied to mailboxes. Leave empty to use the default " "value." -msgstr "" -"Quota par défaut en Mo appliqué aux boites aux lettres. Laisser vide pour " -"utiliser la valeur par défaut." +msgstr "Quota par défaut en Mo appliqué aux boites aux lettres. Laisser vide pour utiliser la valeur par défaut." #: admin/forms/domain.py:47 msgid "" "Alias(es) of this domain. Indicate only one name per input, press ENTER to " "add a new input." -msgstr "" -"Alias de ce domaine. Indiquer seulement un nom par champ, appuyer sur ENTREE " -"pour ajouter un nouveau champ." +msgstr "Alias de ce domaine. Indiquer seulement un nom par champ, appuyer sur ENTREE pour ajouter un nouveau champ." #: admin/forms/domain.py:101 admin/forms/domain.py:113 #: admin/forms/domain.py:121 @@ -382,9 +353,7 @@ msgstr "Nom" msgid "" "The administrator's name. Don't include the domain's name here, it will be " "automatically appended." -msgstr "" -"Le nom de l'administrateur. Ne pas include un nom de domaine ici, il sera " -"ajouté automatiquement." +msgstr "Le nom de l'administrateur. Ne pas include un nom de domaine ici, il sera ajouté automatiquement." #: admin/forms/domain.py:184 msgid "Create aliases" @@ -447,9 +416,7 @@ msgstr "Transférer les messages et conserver une copie dans votre boite locale" msgid "" "You can't define a forward to a local destination. Please ask your " "administrator to create an alias instead." -msgstr "" -"Vous ne pouvez pas définir un transfert vers une destination locale. " -"Veuillez plutôt demander à votre administrateur de créer un alias" +msgstr "Vous ne pouvez pas définir un transfert vers une destination locale. Veuillez plutôt demander à votre administrateur de créer un alias" #: admin/forms/import_.py:11 msgid "Select a file" @@ -469,9 +436,7 @@ msgstr "Chiffrer les mots de passe" #: admin/forms/import_.py:40 msgid "Check this option if passwords contained in your file are not crypted" -msgstr "" -"Cocher cette option si les mots de passe contenus dans votre fichier ne sont " -"pas chiffrés" +msgstr "Cocher cette option si les mots de passe contenus dans votre fichier ne sont pas chiffrés" #: admin/lib.py:31 msgid "A mailbox is required" @@ -490,15 +455,13 @@ msgid "[modoboa] DNSBL issue(s) for domain {}" msgstr "[modoboa] Problème(s) DNSBL pour le domaine {}" #: admin/management/commands/subcommands/_mx.py:180 -#, fuzzy -#| msgid "Domain {} as no MX record" msgid "Domain {} has no MX record" -msgstr "Le domaine {} n'a aucun enregistrement MX" +msgstr "Le domaine {} n'a pas d'enregistrement MX" #: admin/management/commands/subcommands/_mx.py:191 #, python-brace-format msgid "MX record for domain {0} is invalid: {1}" -msgstr "" +msgstr "Enregistrement MX invalide pour le domaine {0} : {1}" #: admin/management/commands/subcommands/_mx.py:207 msgid "[modoboa] MX issue(s) for domain {}" @@ -614,9 +577,7 @@ msgstr "Permission refusée." #: admin/serializers.py:82 msgid "" "List of administered domains (resellers and domain administrators only)." -msgstr "" -"Liste des domaines administrés (revendeurs et administrateurs de domaine " -"seulement)." +msgstr "Liste des domaines administrés (revendeurs et administrateurs de domaine seulement)." #: admin/serializers.py:189 msgid "Not allowed for this role." @@ -745,7 +706,7 @@ msgstr "Statut DNS" #: admin/templates/admin/domain_detail.html:28 #: admin/templates/admin/domains_table.html:12 msgid "Awaiting checks" -msgstr "" +msgstr "En attente de vérification" #: admin/templates/admin/domain_detail.html:40 msgid "Creation date" @@ -866,9 +827,7 @@ msgstr "Mis à jour" #: admin/templates/admin/mx_domain_detail.html:23 msgid "This IP does not match any of the valid MXs defined in parameters" -msgstr "" -"Cette IP ne correspond à un aucun des MX valides déclarés dans les " -"paramètres." +msgstr "Cette IP ne correspond à un aucun des MX valides déclarés dans les paramètres." #: admin/templates/admin/mx_domain_detail.html:36 msgid "No MX record found for this domain." @@ -879,26 +838,19 @@ msgstr "Aucun enregistrement MX trouvé pour ce domaine." msgid "" "Modoboa detected that domain %(domain)s is listed by the following DNSBL " "providers:" -msgstr "" -"Modoboa a détecté que le domaine %(domain)s est listé par les fournisseurs " -"de DNSBL suivants :" +msgstr "Modoboa a détecté que le domaine %(domain)s est listé par les fournisseurs de DNSBL suivants :" #: admin/templates/admin/notifications/domain_in_dnsbl.html:11 msgid "" "The domain's reputation will be affected and there is a chance that emails " "coming from it are considered as spam. You should contact those providers " "and ask them to unlist detected IP address(es)." -msgstr "" -"La réputation de ce domaine sera affectée et il est probable que les emails " -"venant de lui soient considérés comme du spam. Vous devriez contacter ces " -"fournisseurs pour leur demander de délister la/les adresse(s) détectée(s)." +msgstr "La réputation de ce domaine sera affectée et il est probable que les emails venant de lui soient considérés comme du spam. Vous devriez contacter ces fournisseurs pour leur demander de délister la/les adresse(s) détectée(s)." #: admin/templates/admin/notifications/domain_invalid_mx.html:3 #, python-format msgid "Modoboa detected that domain %(domain)s has no valid MX record:" -msgstr "" -"Modoboa a détecté que le domain %(domain)s n'a aucun enregistrement MX " -"valide :" +msgstr "Modoboa a détecté que le domain %(domain)s n'a aucun enregistrement MX valide :" #: admin/templates/admin/quota_headers.html:3 msgid "Value" @@ -1044,19 +996,9 @@ msgid "" "
  • domainalias; name; targeted domain; enabled
  • \n" " %s\n" "\n" -"

    The first element of each line is mandatory and must be equal to one of " -"the previous values.

    \n" +"

    The first element of each line is mandatory and must be equal to one of the previous values.

    \n" "

    You can use a different character as separator.

    \n" -msgstr "" -"Fournir un fichier CSV ou chaque ligne respècte un des formats suivants :\n" -"
      \n" -"
    • domain; nom; quota; activé
    • \n" -"
    • domainalias; nom; domaine cible; activé
    • \n" -" %s\n" -"
    \n" -"

    Le premier élément de chaque ligne est obligatoire et doit être égal à " -"l'une des valeurs précédentes.

    \n" -"

    Vous pouvez utiliser un caractère différent comme séparateur.

    \n" +msgstr "Fournir un fichier CSV ou chaque ligne respècte un des formats suivants :\n
      \n
    • domain; nom; quota; activé
    • \n
    • domainalias; nom; domaine cible; activé
    • \n %s\n
    \n

    Le premier élément de chaque ligne est obligatoire et doit être égal à l'une des valeurs précédentes.

    \n

    Vous pouvez utiliser un caractère différent comme séparateur.

    \n" #: admin/views/import_.py:98 msgid "Import domains" @@ -1066,26 +1008,13 @@ msgstr "Importer des domaines" msgid "" "Provide a CSV file where lines respect one of the following formats:\n" "
      \n" -"
    • account; loginname; password; first name; last name; enabled; group; " -"address; quota; [, domain, ...]
    • \n" +"
    • account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...]
    • \n" "
    • alias; address; enabled; recipient; recipient; ...
    • \n" "
    \n" -"

    The first element of each line is mandatory and must be equal to one of " -"the previous values.

    \n" +"

    The first element of each line is mandatory and must be equal to one of the previous values.

    \n" "\n" "

    You can use a different character as separator.

    \n" -msgstr "" -"Fournir un fichier CSV dans lequel les lignes respectent un des formats " -"suivants :\n" -"
      \n" -"
    • account; loginname; password; first name; last name; enabled; group; " -"address; quota; [, domain, ...]
    • \n" -"
    • alias; address; enabled; recipient; recipient; ...
    • \n" -"
    \n" -"

    Le premier élément de chaque ligne est obligatoire et doit être égal à " -"l'une des valeurs précédentes..

    \n" -"\n" -"

    Vous pouvez utiliser un caractère différent comme séparateur.

    \n" +msgstr "Fournir un fichier CSV dans lequel les lignes respectent un des formats suivants :\n
      \n
    • account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...]
    • \n
    • alias; address; enabled; recipient; recipient; ...
    • \n
    \n

    Le premier élément de chaque ligne est obligatoire et doit être égal à l'une des valeurs précédentes..

    \n\n

    Vous pouvez utiliser un caractère différent comme séparateur.

    \n" #: admin/views/import_.py:130 msgid "Import identities" @@ -1094,6 +1023,3 @@ msgstr "Importer des identités" #: admin/views/user.py:35 msgid "Forward updated" msgstr "Transfert mis à jour" - -#~ msgid "Domain {0} got an invalid MX record. Got {1}" -#~ msgstr "L'enregistrement MX du domaine {0} n'est pas bon : {1}." diff --git a/modoboa/locale/fr/LC_MESSAGES/django.po b/modoboa/locale/fr/LC_MESSAGES/django.po index d3d9b999e..1493f4b53 100644 --- a/modoboa/locale/fr/LC_MESSAGES/django.po +++ b/modoboa/locale/fr/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Antoine Nguyen , 2016 msgid "" @@ -9,13 +9,13 @@ msgstr "" "Project-Id-Version: Modoboa\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-10-06 13:36+0200\n" -"PO-Revision-Date: 2016-09-16 14:04+0000\n" +"PO-Revision-Date: 2016-10-08 07:07+0000\n" "Last-Translator: Antoine Nguyen \n" "Language-Team: French (http://www.transifex.com/tonio/modoboa/language/fr/)\n" -"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: core/__init__.py:63 @@ -64,8 +64,7 @@ msgstr "plain (faible)" #: core/app_settings.py:61 msgid "Scheme used to crypt mailbox passwords" -msgstr "" -"Méthode utilisée pour chiffrer les mots de passe des boites aux lettres" +msgstr "Méthode utilisée pour chiffrer les mots de passe des boites aux lettres" #: core/app_settings.py:66 msgid "Rounds" @@ -75,9 +74,7 @@ msgstr "Tours" msgid "" "Number of rounds to use (only used by sha256crypt and sha512crypt). Must be " "between 1000 and 999999999, inclusive." -msgstr "" -"Nombre de tours à utiliser (sha256crypt et sha512crypt uniquement). Doit " -"être compris entre 1000 et 999999999 inclue." +msgstr "Nombre de tours à utiliser (sha256crypt et sha512crypt uniquement). Doit être compris entre 1000 et 999999999 inclue." #: core/app_settings.py:76 msgid "Secret key" @@ -139,9 +136,7 @@ msgstr "ND de connexion" msgid "" "The distinguished name to use when binding to the LDAP server. Leave empty " "for an anonymous bind" -msgstr "" -"Le nom distinctif à utiliser pour les connections au serveur LDAP. Laisser " -"vide pour une connexion anonyme" +msgstr "Le nom distinctif à utiliser pour les connections au serveur LDAP. Laisser vide pour une connexion anonyme" #: core/app_settings.py:128 msgid "Bind password" @@ -149,9 +144,7 @@ msgstr "Mot de passe de connexion" #: core/app_settings.py:131 msgid "The password to use when binding to the LDAP server (with 'Bind DN')" -msgstr "" -"Le mot de passe à utiliser pour les connections au serveur LDAP (avec 'ND de " -"connexion')" +msgstr "Le mot de passe à utiliser pour les connections au serveur LDAP (avec 'ND de connexion')" #: core/app_settings.py:140 msgid "Users search base" @@ -159,9 +152,7 @@ msgstr "Base de recherche des utilisateurs" #: core/app_settings.py:143 msgid "The distinguished name of the search base used to find users" -msgstr "" -"Le nom distinctif de la base de recherche utilisée pour rechercher les " -"utilisateurs" +msgstr "Le nom distinctif de la base de recherche utilisée pour rechercher les utilisateurs" #: core/app_settings.py:150 msgid "Search filter" @@ -171,9 +162,7 @@ msgstr "Filtre de recherche" msgid "" "An optional filter string (e.g. '(objectClass=person)'). In order to be " "valid, it must be enclosed in parentheses." -msgstr "" -"Un filtre de recherche optionel (ex. '(objectClass=person)'). Pour être " -"valide, il doit être entouré de parenthèses." +msgstr "Un filtre de recherche optionel (ex. '(objectClass=person)'). Pour être valide, il doit être entouré de parenthèses." #: core/app_settings.py:161 msgid "User DN template" @@ -184,9 +173,7 @@ msgstr "Modèle de nom distinctif utilisateur" msgid "" "The template used to construct a user's DN. It should contain one " "placeholder (ie. %(user)s)" -msgstr "" -"Le modèle utilisé pour construire le nom distinctif d'un utilisateur. Il " -"doit contenir un espace réservé (ex. %(user)s)" +msgstr "Le modèle utilisé pour construire le nom distinctif d'un utilisateur. Il doit contenir un espace réservé (ex. %(user)s)" #: core/app_settings.py:172 msgid "Password attribute" @@ -210,12 +197,9 @@ msgstr "Groupes administrateurs" #: core/app_settings.py:189 msgid "" -"Members of those LDAP Posix groups will be created as domain administrators. " -"Use ';' characters to separate groups." -msgstr "" -"Les membres de ces groupes LDAP (Posix) seront créés en tant " -"qu'administrateurs de domaine. Utiliser des caractères ';' pour séparer les " -"groupes." +"Members of those LDAP Posix groups will be created as domain administrators." +" Use ';' characters to separate groups." +msgstr "Les membres de ces groupes LDAP (Posix) seront créés en tant qu'administrateurs de domaine. Utiliser des caractères ';' pour séparer les groupes." #: core/app_settings.py:196 msgid "Group type" @@ -231,9 +215,7 @@ msgstr "Base de recherche des groupes" #: core/app_settings.py:208 msgid "The distinguished name of the search base used to find groups" -msgstr "" -"Le nom distinctif de la base de recherche utilisée pour rechercher les " -"groupes" +msgstr "Le nom distinctif de la base de recherche utilisée pour rechercher les groupes" #: core/app_settings.py:213 msgid "Notifications" @@ -273,9 +255,7 @@ msgstr "Envoyer des statistiques" #: core/app_settings.py:243 msgid "Send statistics to Modoboa public API (counters and used extensions)" -msgstr "" -"Envoyer des statistiques à l'API publique de Modoboa (compteurs et " -"extensions utilisées)" +msgstr "Envoyer des statistiques à l'API publique de Modoboa (compteurs et extensions utilisées)" #: core/app_settings.py:247 msgid "Miscellaneous" @@ -311,8 +291,7 @@ msgstr "Redirection par défaut" #: core/app_settings.py:277 msgid "The default redirection used when no application is specified" -msgstr "" -"La redirection appliquée par défaut quand aucune application n'est spécifiée" +msgstr "La redirection appliquée par défaut quand aucune application n'est spécifiée" #: core/app_settings.py:310 msgid "Key must be either 16, 24, or 32 bytes long" @@ -445,8 +424,7 @@ msgstr "Vous ne pouvez pas supprimer votre propre compte" #: core/models.py:164 msgid "Failed to update password: LDAP module not installed" -msgstr "" -"Echec de la mise à jour du mot de passe : le module LDAP n'est pas installé" +msgstr "Echec de la mise à jour du mot de passe : le module LDAP n'est pas installé" #: core/models.py:222 msgid "account" @@ -504,9 +482,7 @@ msgstr "Dernières nouvelles" msgid "" "Visit the official " "weblog for more information." -msgstr "" -"Visitez le blog " -"officiel pour plus d'information." +msgstr "Visitez le blog officiel pour plus d'information." #: core/templates/core/information.html:2 core/templatetags/core_tags.py:53 msgid "Information" @@ -522,8 +498,7 @@ msgstr "Une ou plusieurs mises à jour sont disponibles!" #: core/templates/core/information.html:6 msgid "Check the following list to find the component(s) that can be updated." -msgstr "" -"Consulter la liste suivante pour trouver le(s) composant(s) concerné(s)." +msgstr "Consulter la liste suivante pour trouver le(s) composant(s) concerné(s)." #: core/templates/core/information.html:10 msgid "Applications" @@ -552,7 +527,7 @@ msgstr "Utilisateurs actifs" #: core/templates/core/information.html:37 msgid "Role" -msgstr "" +msgstr "Rôle" #: core/templates/core/information.html:38 msgid "Last login" @@ -651,9 +626,7 @@ msgstr "Utiliseur '%s' connecté avec succès" #: core/views/auth.py:48 msgid "Your username and password didn't match. Please try again." -msgstr "" -"Votre nom d'utilisateur et mot de passe ne correspondent pas. Veuillez " -"réessayer." +msgstr "Votre nom d'utilisateur et mot de passe ne correspondent pas. Veuillez réessayer." #: core/views/auth.py:76 #, python-format @@ -716,11 +689,11 @@ msgstr "Impossible de mettre à jour le mot de passe : {}" #: lib/templatetags/lib_tags.py:103 msgid "From" -msgstr "" +msgstr "De" #: lib/templatetags/lib_tags.py:103 msgid "To" -msgstr "" +msgstr "À" #: lib/templatetags/lib_tags.py:103 templates/common/email_searchbar.html:17 msgid "Subject" @@ -784,6 +757,3 @@ msgstr "Se souvenir de moi" #: templates/registration/login.html:43 msgid "Log in" msgstr "Se connecter" - -#~ msgid "Group name" -#~ msgstr "Nom du groupe" From a6c092c06cba1ece1ec045d7d84d1c7176e1eaf1 Mon Sep 17 00:00:00 2001 From: Felipe Morato Date: Sun, 9 Oct 2016 00:08:55 -0300 Subject: [PATCH 02/12] Update upgrade.rst Typo fix: `now` -> `know` --- doc/getting_started/upgrade.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/getting_started/upgrade.rst b/doc/getting_started/upgrade.rst index 8f8cb82dc..55ae4a40b 100644 --- a/doc/getting_started/upgrade.rst +++ b/doc/getting_started/upgrade.rst @@ -55,7 +55,7 @@ Specific upgrade instructions An interesting feature brougth by this version is the capability to make different checks about MX records. For example, Modoboa can query main `DNSBL `_ providers -for every defined domain. With this, you will quickly now if one the +for every defined domain. With this, you will quickly know if one the domains you manage is listed or not. To activate it, add the following line to your crontab:: From 00094f7adaf45d852f151a57cc3623b7e2308281 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 10 Oct 2016 13:08:46 +0200 Subject: [PATCH 03/12] Remove deprecated provider and full DNS names. see #921 --- modoboa/admin/constants.py | 1 - modoboa/admin/management/commands/subcommands/_mx.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modoboa/admin/constants.py b/modoboa/admin/constants.py index ce41092be..45704b6d7 100644 --- a/modoboa/admin/constants.py +++ b/modoboa/admin/constants.py @@ -21,7 +21,6 @@ DNSBL_PROVIDERS = [ "dnsbl-3.uceprotect.net", "dnsbl.cyberlogic.net", "dnsbl.inps.de", - "dnsbl.njabl.org", "dnsbl.sorbs.net", "drone.abuse.ch", "duinv.aupads.org", diff --git a/modoboa/admin/management/commands/subcommands/_mx.py b/modoboa/admin/management/commands/subcommands/_mx.py index 8c1a8e7d2..09fe918fe 100644 --- a/modoboa/admin/management/commands/subcommands/_mx.py +++ b/modoboa/admin/management/commands/subcommands/_mx.py @@ -114,7 +114,7 @@ class CheckMXRecords(BaseCommand): results = {} for mx in mx_list: reverse = ".".join(reversed(mx.address.split("."))) - pattern = "{}.{}".format(reverse, provider) + pattern = "{}.{}.".format(reverse, provider) try: results[mx] = socket.gethostbyname(pattern) except socket.gaierror: From fe7d4abe6fb0079cd40a47efc9c1a64dd0097b76 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 12 Oct 2016 10:39:01 +0200 Subject: [PATCH 04/12] Make sure to set the owner. see #937 --- modoboa/admin/tests/test_account.py | 20 +++++++++++++++++++- modoboa/core/models.py | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/modoboa/admin/tests/test_account.py b/modoboa/admin/tests/test_account.py index def372820..ea3080ad4 100644 --- a/modoboa/admin/tests/test_account.py +++ b/modoboa/admin/tests/test_account.py @@ -74,6 +74,24 @@ class AccountTestCase(ModoTestCase): alias__internal=True).exists() ) + def test_delete_default_superadmin(self): + """Delete default superadmin.""" + sadmin2 = core_factories.UserFactory( + username="admin2", is_superuser=True) + sadmin = User.objects.get(username="admin") + self.client.force_login(sadmin2) + self.ajax_post( + reverse("admin:account_delete", args=[sadmin.pk]), {} + ) + values = { + "username": "user@test.com", "role": "DomainAdmins", + "is_active": True, "email": "user@test.com" + } + account = User.objects.get(username="user@test.com") + self.ajax_post( + reverse("admin:account_change", args=[account.pk]), values + ) + def test_sender_address(self): """Check if sender addresses are saved.""" account = User.objects.get(username="user@test.com") @@ -198,7 +216,7 @@ class AccountTestCase(ModoTestCase): self.assertIn("Resources usage", response.content) -@skipIf(NO_LDAP, 'No ldap module installed') +@skipIf(NO_LDAP, "No ldap module installed") @override_settings(AUTHENTICATION_BACKENDS=( 'modoboa.lib.authbackends.LDAPBackend', 'modoboa.lib.authbackends.SimpleBackend', diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 39816d66f..5af31543b 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -118,6 +118,9 @@ class User(PermissionsMixin): raise PermDeniedException owner = get_object_owner(self) + if owner == self: + # The default admin is being removed... + owner = fromuser for ooentry in self.objectaccess_set.filter(is_owner=True): if ooentry.content_object is not None: grant_access_to_object(owner, ooentry.content_object, True) From 327b0a557f87300685472bd8587b89dafc3b47f7 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 12 Oct 2016 11:29:21 +0200 Subject: [PATCH 05/12] Added missing upgrade instruction. fix #926 --- doc/getting_started/upgrade.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/getting_started/upgrade.rst b/doc/getting_started/upgrade.rst index 55ae4a40b..8b79350d1 100644 --- a/doc/getting_started/upgrade.rst +++ b/doc/getting_started/upgrade.rst @@ -73,6 +73,16 @@ configuration as follows:: MODOBOA_API_URL = 'https://api.modoboa.org/1/' +Finally, it is now possible to declare additional sender addresses on +a per-account basis. You need to update your postfix configuration in +order to use this functionality. Just edit the :file:`main.cf` file +and change the following parameter:: + + smtpd_sender_login_maps = + :/etc/postfix/sql-sender-login-mailboxes.cf + :/etc/postfix/sql-sender-login-aliases.cf + :/etc/postfix/sql-sender-login-mailboxes-extra.cf + 1.5.0 ===== From f3586789d72b426adaba517b8eb760f5996a8693 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 12 Oct 2016 11:30:55 +0200 Subject: [PATCH 06/12] Removed deprecated property. --- modoboa/core/models.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 5af31543b..d2ef47cdb 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -242,16 +242,6 @@ class User(PermissionsMixin): return "%s %s" % (self.first_name, self.last_name) return "----" - @property - def group(self): - """FIXME: DEPRECATED""" - if self.is_superuser: - return "SuperAdmins" - try: - return self.groups.all()[0].name - except IndexError: - return "---" - @property def enabled(self): return self.is_active From e2703e45c2e47dc28ef3c3ea0c47cc2291f653e4 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 12 Oct 2016 14:32:49 +0200 Subject: [PATCH 07/12] Version 1.6.1 --- doc/conf.py | 2 +- setup.py | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 5272f3e50..44da751d4 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -52,7 +52,7 @@ copyright = u'2016, Antoine Nguyen' # The short X.Y version. version = '1.6' # The full version, including alpha/beta/rc tags. -release = '1.6.0' +release = '1.6.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index 0fa5090f0..7554a2a39 100644 --- a/setup.py +++ b/setup.py @@ -54,24 +54,24 @@ def read(fname): setup( name="modoboa", - version='1.6.0', - url='http://modoboa.org/', - license='MIT', + version="1.6.1", + url="http://modoboa.org/", + license="ISC", description="Mail hosting made simple", - long_description=read('README.rst'), - author='Antoine Nguyen', - author_email='tonio@ngyn.org', + long_description=read("README.rst"), + author="Antoine Nguyen", + author_email="tonio@ngyn.org", packages=find_packages(), include_package_data=True, scripts=["bin/modoboa-admin.py"], zip_safe=False, install_requires=parse_requirements(PIP_REQUIRES), dependency_links=parse_dependency_links(PIP_REQUIRES), - classifiers=['Development Status :: 5 - Production/Stable', - 'Framework :: Django', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Topic :: Internet :: WWW/HTTP'] + classifiers=["Development Status :: 5 - Production/Stable", + "Framework :: Django", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Internet :: WWW/HTTP"] ) From a58f1204c58df578a3081e6268371dd3f76886f1 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 13 Oct 2016 14:13:12 +0200 Subject: [PATCH 08/12] Update README.rst Remove stats --- README.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.rst b/README.rst index bc2388426..e950c8616 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ `Modoboa `_ ################################ -|travis| |codecov| |landscape| |latest-version| |downloads| +|travis| |codecov| |landscape| |latest-version| Modoboa is a mail hosting and management platform including a modern and simplified Web User Interface. It provides useful components such @@ -58,9 +58,6 @@ The following external libraries are provided with Modoboa: .. |landscape| image:: https://landscape.io/github/tonioo/modoboa/master/landscape.svg?style=flat :target: https://landscape.io/github/tonioo/modoboa/master :alt: Code Health -.. |downloads| image:: https://img.shields.io/pypi/dm/modoboa.svg - :target: https://pypi.python.org/pypi/modoboa/ - :alt: Downloads from Pypi .. |travis| image:: https://travis-ci.org/tonioo/modoboa.png?branch=master :target: https://travis-ci.org/tonioo/modoboa .. |codecov| image:: http://codecov.io/github/tonioo/modoboa/coverage.svg?branch=master From 0ff6de98ad4f2dfa6c33b9fb6cad22b0e97f1eb6 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 13 Oct 2016 21:59:26 +0200 Subject: [PATCH 09/12] Fixed syntax error. fix #940 --- modoboa/admin/postfix_maps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modoboa/admin/postfix_maps.py b/modoboa/admin/postfix_maps.py index b8e19a3b0..9eca03ed4 100644 --- a/modoboa/admin/postfix_maps.py +++ b/modoboa/admin/postfix_maps.py @@ -125,13 +125,13 @@ class SenderLoginMailboxExtraMap(object): "WHERE sad.address='%s'" ) postgres = ( - "SELECT mb.address || '@' || dom.name) FROM admin_mailbox mb " + "SELECT mb.address || '@' || dom.name FROM admin_mailbox mb " "INNER JOIN admin_senderaddress sad ON sad.mailbox_id=mb.id " "INNER JOIN admin_domain dom ON dom.id=mb.domain_id " "WHERE sad.address='%s'" ) sqlite = ( - "SELECT mb.address || '@' || dom.name) FROM admin_mailbox mb " + "SELECT mb.address || '@' || dom.name FROM admin_mailbox mb " "INNER JOIN admin_senderaddress sad ON sad.mailbox_id=mb.id " "INNER JOIN admin_domain dom ON dom.id=mb.domain_id " "WHERE sad.address='%s'" From 5e0b5de94afcdf917237434cef91b405c4c8fc1d Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 14 Oct 2016 14:24:10 +0200 Subject: [PATCH 10/12] Improve documentation. see #942 --- modoboa/admin/api.py | 9 ++++++--- modoboa/admin/serializers.py | 8 ++++++-- modoboa/core/commands/templates/settings.py.tpl | 8 ++++++-- requirements.txt | 2 +- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/modoboa/admin/api.py b/modoboa/admin/api.py index c8c39fa92..24684c4fa 100644 --- a/modoboa/admin/api.py +++ b/modoboa/admin/api.py @@ -56,9 +56,12 @@ class AccountViewSet(viewsets.ModelViewSet): def get_serializer_class(self): """Return a serializer.""" - if self.request.method == "GET": - return serializers.AccountSerializer - return serializers.WritableAccountSerializer + action_dict = { + "list": serializers.AccountSerializer, + "retrive": serializers.AccountSerializer + } + return action_dict.get( + self.action, serializers.WritableAccountSerializer) def get_queryset(self): """Filter queryset based on current user.""" diff --git a/modoboa/admin/serializers.py b/modoboa/admin/serializers.py index 8a842f5ae..a37907d86 100644 --- a/modoboa/admin/serializers.py +++ b/modoboa/admin/serializers.py @@ -8,6 +8,7 @@ from rest_framework import serializers from passwords import validators from modoboa.admin import models as admin_models +from modoboa.core import constants as core_constants from modoboa.core import models as core_models from modoboa.core import signals as core_signals from modoboa.lib import exceptions as lib_exceptions @@ -154,6 +155,8 @@ class AccountPasswordSerializer(serializers.ModelSerializer): class WritableAccountSerializer(AccountSerializer): """Serializer to create account.""" + role = serializers.ChoiceField(choices=core_constants.ROLES) + class Meta(AccountSerializer.Meta): fields = AccountSerializer.Meta.fields + ( "password", ) @@ -184,11 +187,12 @@ class WritableAccountSerializer(AccountSerializer): def validate(self, data): """Check constraints.""" master_user = data.get("master_user", False) - if master_user and data["role"] != "SuperAdmins": + role = data.get("role") + if master_user and role != "SuperAdmins": raise serializers.ValidationError({ "master_user": _("Not allowed for this role.") }) - if data["role"] == "SimpleUsers": + if role == "SimpleUsers": mailbox = data.get("mailbox") if mailbox is None: data["mailbox"] = { diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl index 655702486..5eb1d00e0 100644 --- a/modoboa/core/commands/templates/settings.py.tpl +++ b/modoboa/core/commands/templates/settings.py.tpl @@ -167,8 +167,12 @@ SWAGGER_SETTINGS = { "exclude_namespaces": [], "info": { "contact": "contact@modoboa.com", - "description": ("Modoboa API, requires a valid token."), - "title": "Modoboa API", + "description": ( + "Modoboa API, requires a valid token. To obtain a token, login " + "as super administrator, go to 'User settings > API' and enable " + "API access. Click on 'Update' and wait for page refresh." + ), + "title": "Modoboa API documentation", } } diff --git a/requirements.txt b/requirements.txt index c11bde24b..1bad2a489 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ django-xforwardedfor-middleware django-passwords==0.3.10 rfc6266 progressbar==2.3 -djangorestframework==3.3.1 +djangorestframework==3.3.3 django-rest-swagger==0.3.5 django-subcommand2==0.1.1 gevent==1.1.1 From 6c6f440f84dc69e8ab710c093984b96445de20a5 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 14 Oct 2016 17:50:43 +0200 Subject: [PATCH 11/12] Catch LookupError exception. fix #944 --- modoboa/lib/u2u_decode.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/modoboa/lib/u2u_decode.py b/modoboa/lib/u2u_decode.py index 7ff7c8fee..085e714e8 100644 --- a/modoboa/lib/u2u_decode.py +++ b/modoboa/lib/u2u_decode.py @@ -1,12 +1,9 @@ -#!/usr/bin/env python # coding: utf-8 -""" -u2u_decode.py -unstructured rfc2047 header to unicode -""" -import re +"""Unstructured rfc2047 header to unicode.""" + from email.header import decode_header, make_header +import re # check spaces between encoded_words (and strip them) sre = re.compile(r'\?=[ \t]+=\?') @@ -15,7 +12,7 @@ mre = re.compile(r'=\?[^?]*?\?[bq]\?[^?\t]*?\?=', re.I) def clean_spaces(m): - """Replace unencoded spaces in string + """Replace unencoded spaces in string. :param str m: a match object :return: the cleaned string @@ -24,12 +21,11 @@ def clean_spaces(m): def decode_mime(m): - """substitute matching encoded_word with unicode equiv. - """ + """Substitute matching encoded_word with unicode equiv.""" h = decode_header(clean_spaces(m)) try: u = unicode(make_header(h)) - except UnicodeDecodeError: + except (LookupError, UnicodeDecodeError): return m.group(0) return u From 3f994c76b7b3c9eb5b77e58482f33496476d031b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20de=20l=27Epine?= Date: Fri, 14 Oct 2016 23:13:36 +0200 Subject: [PATCH 12/12] Update account.py tip update on the alias field according the new wildcard syntax (without '*') --- modoboa/admin/forms/account.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modoboa/admin/forms/account.py b/modoboa/admin/forms/account.py index 63ed90e1e..36246ba38 100644 --- a/modoboa/admin/forms/account.py +++ b/modoboa/admin/forms/account.py @@ -206,8 +206,8 @@ class AccountFormMail(forms.Form, DynamicForm): required=False, help_text=ugettext_lazy( "Alias(es) of this mailbox. Indicate only one address per input, " - "press ENTER to add a new input. Use the '*' character to create " - "a 'catchall' alias (ex: *@domain.tld)." + "press ENTER to add a new input. To create a catchall alias, just " + "enter the domain name (@domain.tld)." ) ) senderaddress = lib_fields.UTF8AndEmptyUserEmailField(