mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
merge from master
This commit is contained in:
@@ -6,8 +6,16 @@ name: Modoboa App
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- 'modoboa/**.po'
|
||||
- 'frontend/**'
|
||||
- 'doc/**'
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- 'modoboa/**.po'
|
||||
- 'frontend/**'
|
||||
- 'doc/**'
|
||||
release:
|
||||
branches: [ master ]
|
||||
types: [ published ]
|
||||
@@ -93,7 +101,7 @@ jobs:
|
||||
run: |
|
||||
python ./tests.py
|
||||
cd test_project
|
||||
python3 manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.transport modoboa.relaydomains modoboa.dnstools modoboa.ldapsync modoboa.policyd modoboa.maillog modoboa.parameters
|
||||
python3 manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.transport modoboa.relaydomains modoboa.dnstools modoboa.ldapsync modoboa.policyd modoboa.maillog modoboa.parameters modoboa.dmarc
|
||||
env:
|
||||
# use localhost for the host here because we are running the job on the VM.
|
||||
# If we were running the job on in a container this would be postgres
|
||||
@@ -109,7 +117,7 @@ jobs:
|
||||
run: |
|
||||
python ./tests.py
|
||||
cd test_project
|
||||
coverage run manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.transport modoboa.relaydomains modoboa.dnstools modoboa.ldapsync modoboa.policyd modoboa.maillog modoboa.parameters
|
||||
coverage run manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.transport modoboa.relaydomains modoboa.dnstools modoboa.ldapsync modoboa.policyd modoboa.maillog modoboa.parameters modoboa.dmarc
|
||||
coverage combine
|
||||
env:
|
||||
# use localhost for the host here because we are running the job on the VM.
|
||||
|
||||
+12
-4
@@ -1,13 +1,13 @@
|
||||
queue_rules:
|
||||
- name: default
|
||||
conditions:
|
||||
- check-success=test (postgres, 3.7)
|
||||
- check-success=test (postgres, 3.9)
|
||||
|
||||
|
||||
pull_request_rules:
|
||||
- name: automatic merge on CI success and review
|
||||
conditions:
|
||||
- check-success=test (postgres, 3.7)
|
||||
- check-success=test (postgres, 3.9)
|
||||
- "#approved-reviews-by>=1"
|
||||
- "#review-requested=0"
|
||||
- "#changes-requested-reviews-by=0"
|
||||
@@ -24,7 +24,7 @@ pull_request_rules:
|
||||
- name: automatic merge for pyUp pull requests
|
||||
conditions:
|
||||
- author=pyup-bot
|
||||
- check-success=test (postgres, 3.7)
|
||||
- check-success=test (postgres, 3.9)
|
||||
- label=dependencies
|
||||
- "#approved-reviews-by>=1"
|
||||
actions:
|
||||
@@ -34,10 +34,18 @@ pull_request_rules:
|
||||
- name: automatic merge for dependabot pull requests
|
||||
conditions:
|
||||
- author~=^dependabot(|-preview)\[bot\]$
|
||||
- check-success=test (postgres, 3.7)
|
||||
- check-success=test (postgres, 3.9)
|
||||
- label=dependencies
|
||||
- "#approved-reviews-by>=1"
|
||||
actions:
|
||||
queue:
|
||||
method: squash
|
||||
name: default
|
||||
- name: automatic merge for transifex pull requests
|
||||
conditions:
|
||||
- author~=^transifex-integration\[bot\]$
|
||||
- "#approved-reviews-by>=1"
|
||||
actions:
|
||||
queue:
|
||||
method: squash
|
||||
name: default
|
||||
|
||||
+37
-4
@@ -66,7 +66,7 @@ New admin interface won't update by itself. Run the following commands to update
|
||||
> rm -rf frontend
|
||||
> cp -R <virtuenv_path>/lib/pythonX.X/site-packages/modoboa/frontend_dist/ frontend/
|
||||
> cp ./config.json frontend/config.json
|
||||
|
||||
|
||||
Extensions
|
||||
**********
|
||||
|
||||
@@ -108,7 +108,40 @@ Rebuild Virtual Environment
|
||||
Specific instructions
|
||||
*********************
|
||||
|
||||
2.0.4
|
||||
2.1.0
|
||||
=====
|
||||
|
||||
The ``modoboa-dmarc`` plugin has been merged into the core.
|
||||
|
||||
Add ``'modoboa.dmarc'`` to ``MODOBOA_APPS``:
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
MODOBOA_APPS = (
|
||||
'modoboa',
|
||||
'modoboa.core',
|
||||
'modoboa.lib',
|
||||
'modoboa.admin',
|
||||
'modoboa.transport',
|
||||
'modoboa.relaydomains',
|
||||
'modoboa.limits',
|
||||
'modoboa.parameters',
|
||||
'modoboa.dnstools',
|
||||
'modoboa.policyd',
|
||||
'modoboa.maillog',
|
||||
'modoboa.dmarc',
|
||||
)
|
||||
|
||||
And remove any reference to ``modoboa_dmarc`` in this same variable.
|
||||
|
||||
FIXME: INSTALLATION django-rename-app
|
||||
|
||||
.. sourcecode:: bash
|
||||
|
||||
python manage.py rename_app modoboa_dmarc dmarc
|
||||
|
||||
|
||||
2.0.4t
|
||||
=====
|
||||
|
||||
The following modifications must be applied to the :file:`settings.py` file:
|
||||
@@ -159,7 +192,7 @@ The following modifications must be applied to the :file:`settings.py` file:
|
||||
},
|
||||
|
||||
|
||||
* You now have the possibility to customize the url of the new-admin interface.
|
||||
* You now have the possibility to customize the url of the new-admin interface.
|
||||
To do so please head up to :ref:`the custom configuration chapter <customization>` (advanced user).
|
||||
|
||||
* Add ``DEFAULT_THROTTLE_RATES`` to ``REST_FRAMEWORK``:
|
||||
@@ -187,7 +220,7 @@ The following modifications must be applied to the :file:`settings.py` file:
|
||||
|
||||
* You can edit the ``DEFAULT_THROTTLE_RATES`` to whatever value suits you.
|
||||
- `user` is for every endpoint, it is per user or per ip if not logged.
|
||||
- `ddos` is per api endpoint and per user or per ip if not logged.
|
||||
- `ddos` is per api endpoint and per user or per ip if not logged.
|
||||
- `ddos_lesser` is for per api endpoint and per user or per ip if not logged. This is for api endpoint that are lighter.
|
||||
- `login` the number of time an ip can attempt to log. The counter will reset on login success.
|
||||
- `password_` is for the recovery, it is divided per step in the recovery process.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ INPUT_DIR = src
|
||||
OUTPUT_DIR = .
|
||||
|
||||
# Available locales for the app.
|
||||
LOCALES = en fr
|
||||
LOCALES = br cs de el es en fi fr it ja nl pt pt-br pl po ru sv tr zh-hant
|
||||
|
||||
# Name of the generated .po files for each available locale.
|
||||
LOCALE_FILES ?= $(patsubst %,$(OUTPUT_DIR)/locale/%/LC_MESSAGES/app.po,$(LOCALES))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-10-27 16:52+0200\n"
|
||||
"POT-Creation-Date: 2023-02-23 18:08+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: en\n"
|
||||
@@ -177,7 +177,11 @@ msgstr ""
|
||||
msgid "Aliases"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/layout/Navbar.vue:93 src/components/layout/Navbar.vue:208
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:4
|
||||
msgid "Alignment"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/layout/Navbar.vue:99 src/components/layout/Navbar.vue:214
|
||||
msgid "API"
|
||||
msgstr ""
|
||||
|
||||
@@ -244,6 +248,11 @@ msgstr ""
|
||||
msgid "Bind/named format. Click to copy"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryForm.vue:26
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:19
|
||||
msgid "body"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/domains/DomainForm.vue:122
|
||||
#: src/components/identities/AccountForm.vue:94
|
||||
#: src/components/identities/AliasForm.vue:55
|
||||
@@ -252,6 +261,14 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:10
|
||||
msgid "Change password"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/admin/ComponentsInformationTable.vue:8
|
||||
msgid "Check out the following list to find related components"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/identities/Identities.vue:45 src/views/identities/Identities.vue:1
|
||||
msgid "Check this option if passwords contained in your file are not crypted"
|
||||
msgstr ""
|
||||
@@ -274,6 +291,10 @@ msgstr ""
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alarms/AlarmList.vue:21 src/components/alarms/AlarmList.vue:5
|
||||
msgid "Closed"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tools/CreationForm.vue:40
|
||||
msgid "Confirm and create"
|
||||
msgstr ""
|
||||
@@ -288,7 +309,7 @@ msgstr ""
|
||||
msgid "Congratulations! Two-Factor Authentication is now enabled for your account."
|
||||
msgstr ""
|
||||
|
||||
#: src/views/Login.vue:21
|
||||
#: src/views/Login.vue:23
|
||||
msgid "Connect"
|
||||
msgstr ""
|
||||
|
||||
@@ -363,16 +384,15 @@ msgstr ""
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alarms/AlarmList.vue:8
|
||||
#: src/components/logs/AuditTrailList.vue:8
|
||||
#: src/components/logs/MessageList.vue:9 src/components/alarms/AlarmList.vue:48
|
||||
#: src/components/logs/MessageList.vue:10
|
||||
#: src/components/logs/AuditTrailList.vue:40
|
||||
#: src/components/logs/MessageList.vue:42
|
||||
#: src/components/logs/MessageList.vue:43
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tools/TimeSerieChart.vue:51
|
||||
#: src/components/tools/TimeSerieChart.vue:109
|
||||
#: src/components/tools/TimeSerieChart.vue:50
|
||||
#: src/components/tools/TimeSerieChart.vue:108
|
||||
msgid "Day"
|
||||
msgstr ""
|
||||
|
||||
@@ -401,14 +421,20 @@ msgstr ""
|
||||
msgid "Delete token"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/admin/ComponentsInformationTable.vue:16
|
||||
#: src/components/identities/AliasCreationForm.vue:31
|
||||
#: src/components/identities/AliasGeneralForm.vue:87
|
||||
#: src/components/identities/AliasSummary.vue:19
|
||||
#: src/components/identities/AliasCreationForm.vue:51
|
||||
#: src/components/identities/AliasGeneralForm.vue:56
|
||||
#: src/components/admin/ComponentsInformationTable.vue:54
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:37
|
||||
msgid "Detail"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/user/TwoFactorAuthForm.vue:57
|
||||
#: src/components/user/TwoFactorAuthForm.vue:5
|
||||
msgid "Disable 2FA"
|
||||
@@ -459,6 +485,10 @@ msgstr ""
|
||||
msgid "DKIM signing"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domains/Domain.vue:17
|
||||
msgid "DMARC"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/domains/DNSDetail.vue:79
|
||||
#: src/components/domains/DNSDetail.vue:43
|
||||
msgid "DMARC record found"
|
||||
@@ -469,6 +499,10 @@ msgstr ""
|
||||
msgid "DMARC record not found"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:50
|
||||
msgid "DMARC support does not seem to be enabled for this domain."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/domains/DomainCreationForm.vue:31
|
||||
#: src/components/domains/DomainCreationForm.vue:109
|
||||
#: src/components/domains/DomainCreationForm.vue:115
|
||||
@@ -509,11 +543,11 @@ msgstr ""
|
||||
msgid "Do you really want to delete the alias %{ alias }?"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alarms/AlarmList.vue:9
|
||||
#: src/components/alarms/AlarmList.vue:10
|
||||
#: src/components/identities/AliasGeneralForm.vue:56
|
||||
#: src/views/domains/Domain.vue:3 src/views/domains/Domains.vue:20
|
||||
#: src/components/identities/AliasGeneralForm.vue:31
|
||||
#: src/components/alarms/AlarmList.vue:49
|
||||
#: src/components/alarms/AlarmList.vue:74
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
@@ -601,6 +635,10 @@ msgstr ""
|
||||
msgid "Edit domain alias"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:59
|
||||
msgid "element"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/identities/AccountCreationForm.vue:48
|
||||
#: src/components/identities/AccountCreationForm.vue:98
|
||||
msgid "Email"
|
||||
@@ -659,6 +697,20 @@ msgstr ""
|
||||
msgid "Enter the code from the two-factor app on your mobile device. If you have lost your device, you may enter one of your recovery codes."
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:11
|
||||
msgid "Enter the code you've just received by SMS"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryForm.vue:62
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:73
|
||||
msgid "err"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:18
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:66
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/identities/AccountMailboxForm.vue:5
|
||||
msgid "Ex: 10MB. Leave empty for no limit"
|
||||
msgstr ""
|
||||
@@ -679,6 +731,13 @@ msgstr ""
|
||||
msgid "Export domains and aliases to CSV"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:25
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:37
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:143
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:155
|
||||
msgid "Failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/identities/AccountCreationForm.vue:30
|
||||
#: src/components/identities/AccountGeneralForm.vue:32
|
||||
#: src/components/user/ProfileForm.vue:45
|
||||
@@ -688,12 +747,13 @@ msgstr ""
|
||||
msgid "First name"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/Login.vue:16
|
||||
#: src/views/Login.vue:17 src/views/user/PasswordRecoveryChangeForm.vue:6
|
||||
#: src/views/user/PasswordRecoveryForm.vue:6
|
||||
msgid "Forgot password?"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/layout/Navbar.vue:117 src/views/user/Forward.vue:3
|
||||
#: src/components/layout/Navbar.vue:232
|
||||
#: src/components/layout/Navbar.vue:123 src/views/user/Forward.vue:3
|
||||
#: src/components/layout/Navbar.vue:238
|
||||
msgid "Forward"
|
||||
msgstr ""
|
||||
|
||||
@@ -706,9 +766,20 @@ msgstr ""
|
||||
msgid "Forward updated"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/logs/MessageList.vue:12
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:24
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:36
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:142
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:154
|
||||
msgid "Forwarded"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:42
|
||||
msgid "Forwarders with ARC"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/logs/MessageList.vue:13
|
||||
#: src/components/tools/TimeSerieChart.vue:17
|
||||
#: src/components/logs/MessageList.vue:45
|
||||
#: src/components/logs/MessageList.vue:46
|
||||
msgid "From"
|
||||
msgstr ""
|
||||
|
||||
@@ -721,13 +792,20 @@ msgstr ""
|
||||
msgid "Fullname/recipient"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:22
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:34
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:140
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:152
|
||||
msgid "Fully aligned"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/domains/DomainCreationForm.vue:23
|
||||
#: src/components/domains/DomainCreationForm.vue:108
|
||||
#: src/components/domains/DomainCreationForm.vue:114
|
||||
#: src/components/domains/DomainForm.vue:7
|
||||
#: src/components/identities/AliasCreationForm.vue:17
|
||||
#: src/components/identities/AliasCreationForm.vue:49
|
||||
#: src/components/identities/AliasForm.vue:7
|
||||
#: src/components/identities/AliasForm.vue:7 src/views/domains/Domain.vue:11
|
||||
#: src/components/identities/AliasCreationForm.vue:37
|
||||
#: src/components/identities/AliasCreationForm.vue:69
|
||||
#: src/components/domains/DomainCreationForm.vue:74
|
||||
@@ -791,6 +869,10 @@ msgstr ""
|
||||
msgid "If you close this form now, your modifications won't be saved. Do you confirm?"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:52
|
||||
msgid "If you configured it recently, please wait for the first report to be received and processed."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tools/ImportForm.vue:29
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
@@ -815,6 +897,11 @@ msgstr ""
|
||||
msgid "Indicate one or more recipients separated by a comma (,)"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/layout/Navbar.vue:92 src/views/admin/Information.vue:3
|
||||
#: src/components/layout/Navbar.vue:207
|
||||
msgid "Information"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/user/TwoFactorAuthForm.vue:14
|
||||
#: src/components/user/TwoFactorAuthForm.vue:7
|
||||
msgid ""
|
||||
@@ -823,7 +910,21 @@ msgid ""
|
||||
" app to scan this QR code."
|
||||
msgstr ""
|
||||
|
||||
#: src/views/Login.vue:35 src/views/Login.vue:93
|
||||
#: src/components/admin/ComponentsInformationTable.vue:3
|
||||
msgid "Installed components"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/admin/ComponentsInformationTable.vue:14
|
||||
#: src/components/admin/ComponentsInformationTable.vue:52
|
||||
msgid "Installed version"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:54
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:114
|
||||
msgid "Invalid reset token."
|
||||
msgstr ""
|
||||
|
||||
#: src/views/Login.vue:35 src/views/Login.vue:95
|
||||
msgid "Invalid username and/or password"
|
||||
msgstr ""
|
||||
|
||||
@@ -863,6 +964,11 @@ msgstr ""
|
||||
msgid "Last name"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/admin/ComponentsInformationTable.vue:15
|
||||
#: src/components/admin/ComponentsInformationTable.vue:53
|
||||
msgid "Latest version"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/identities/AccountMailboxForm.vue:8
|
||||
msgid "Leave empty for no limit"
|
||||
msgstr ""
|
||||
@@ -887,8 +993,8 @@ msgstr ""
|
||||
msgid "Logger"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/layout/Navbar.vue:133 src/components/layout/Topbar.vue:6
|
||||
#: src/components/layout/Navbar.vue:248 src/components/layout/Topbar.vue:53
|
||||
#: src/components/layout/Navbar.vue:139 src/components/layout/Topbar.vue:6
|
||||
#: src/components/layout/Navbar.vue:254 src/components/layout/Topbar.vue:53
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
@@ -896,13 +1002,13 @@ msgstr ""
|
||||
msgid "Logs"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alarms/AlarmList.vue:10
|
||||
#: src/components/alarms/AlarmList.vue:11
|
||||
#: src/components/identities/AccountCreationForm.vue:46
|
||||
#: src/components/identities/AccountCreationForm.vue:89
|
||||
#: src/components/identities/AccountForm.vue:56
|
||||
#: src/components/identities/AccountCreationForm.vue:96
|
||||
#: src/components/identities/AccountCreationForm.vue:139
|
||||
#: src/components/alarms/AlarmList.vue:50
|
||||
#: src/components/alarms/AlarmList.vue:75
|
||||
msgid "Mailbox"
|
||||
msgstr ""
|
||||
|
||||
@@ -910,9 +1016,9 @@ msgstr ""
|
||||
msgid "Mailboxes"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alarms/AlarmList.vue:11
|
||||
#: src/components/alarms/AlarmList.vue:12
|
||||
#: src/components/logs/AuditTrailList.vue:11
|
||||
#: src/components/alarms/AlarmList.vue:51
|
||||
#: src/components/alarms/AlarmList.vue:76
|
||||
#: src/components/logs/AuditTrailList.vue:43
|
||||
msgid "Message"
|
||||
msgstr ""
|
||||
@@ -945,8 +1051,8 @@ msgstr ""
|
||||
msgid "Modify"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tools/TimeSerieChart.vue:53
|
||||
#: src/components/tools/TimeSerieChart.vue:111
|
||||
#: src/components/tools/TimeSerieChart.vue:52
|
||||
#: src/components/tools/TimeSerieChart.vue:110
|
||||
msgid "Month"
|
||||
msgstr ""
|
||||
|
||||
@@ -954,6 +1060,7 @@ msgstr ""
|
||||
msgid "MX records"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/admin/ComponentsInformationTable.vue:13
|
||||
#: src/components/domains/AdministratorList.vue:19
|
||||
#: src/components/domains/DNSDetail.vue:18
|
||||
#: src/components/domains/DomainAliasForm.vue:40
|
||||
@@ -967,6 +1074,7 @@ msgstr ""
|
||||
#: src/components/domains/DomainCreationForm.vue:76
|
||||
#: src/components/domains/AdministratorList.vue:87
|
||||
#: src/components/domains/DomainList.vue:166
|
||||
#: src/components/admin/ComponentsInformationTable.vue:51
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@@ -1041,11 +1149,24 @@ msgstr ""
|
||||
msgid "Number of messages this mailbox can send per day. Leave empty for no limit."
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryForm.vue:31
|
||||
#: src/views/user/PasswordRecoveryForm.vue:77
|
||||
msgid "Ok"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/layout/ConfirmDialog.vue:15
|
||||
#: src/components/layout/ConfirmDialog.vue:54
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/admin/ComponentsInformationTable.vue:7
|
||||
msgid "One or more updates are available"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alarms/AlarmList.vue:18 src/components/alarms/AlarmList.vue:2
|
||||
msgid "Opened"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/alarms/Alarms.vue:3
|
||||
msgid "Opened alarms"
|
||||
msgstr ""
|
||||
@@ -1062,6 +1183,17 @@ msgstr ""
|
||||
msgid "Parameters updated"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:23
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:35
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:141
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:153
|
||||
msgid "Partially aligned"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:41
|
||||
msgid "Partially trusted sources / Forwarders"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/identities/AccountPasswordForm.vue:88
|
||||
#: src/components/user/ProfileForm.vue:21 src/views/Login.vue:13
|
||||
#: src/components/identities/AccountPasswordForm.vue:42
|
||||
@@ -1077,6 +1209,10 @@ msgstr ""
|
||||
msgid "Password copied to clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:8
|
||||
msgid "Password recovery"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/user/ProfileForm.vue:42
|
||||
#: src/components/user/ProfileForm.vue:112
|
||||
msgid "Password updated"
|
||||
@@ -1107,6 +1243,10 @@ msgstr ""
|
||||
msgid "Pin code"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryForm.vue:9
|
||||
msgid "Please fill-in your primary email address"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/domains/DNSStatusChip.vue:12
|
||||
#: src/components/domains/DNSStatusChip.vue:19
|
||||
msgid "Problem"
|
||||
@@ -1116,9 +1256,9 @@ msgstr ""
|
||||
msgid "Proceed"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/layout/Navbar.vue:100 src/components/layout/Navbar.vue:127
|
||||
#: src/views/user/Profile.vue:3 src/components/layout/Navbar.vue:215
|
||||
#: src/components/layout/Navbar.vue:242
|
||||
#: src/components/layout/Navbar.vue:106 src/components/layout/Navbar.vue:133
|
||||
#: src/views/user/Profile.vue:3 src/components/layout/Navbar.vue:221
|
||||
#: src/components/layout/Navbar.vue:248
|
||||
msgid "Profile"
|
||||
msgstr ""
|
||||
|
||||
@@ -1131,7 +1271,7 @@ msgstr ""
|
||||
msgid "Provide a CSV file where lines respect one of the following formats:"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/logs/MessageList.vue:8 src/components/logs/MessageList.vue:41
|
||||
#: src/components/logs/MessageList.vue:9 src/components/logs/MessageList.vue:42
|
||||
msgid "Queue ID"
|
||||
msgstr ""
|
||||
|
||||
@@ -1212,7 +1352,7 @@ msgstr ""
|
||||
msgid "Relay"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/Login.vue:17
|
||||
#: src/views/Login.vue:19
|
||||
msgid "Remember me"
|
||||
msgstr ""
|
||||
|
||||
@@ -1231,6 +1371,10 @@ msgstr ""
|
||||
msgid "Reseller"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:21
|
||||
msgid "Resend SMS."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/user/TwoFactorAuthForm.vue:60
|
||||
#: src/components/user/TwoFactorAuthForm.vue:8
|
||||
msgid "Reset recovery codes"
|
||||
@@ -1245,6 +1389,20 @@ msgstr ""
|
||||
msgid "Resources usage"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:23
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:71
|
||||
msgid "Retry reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:24
|
||||
#: src/views/user/PasswordRecoveryForm.vue:19
|
||||
#: src/views/user/PasswordRecoveryForm.vue:32
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:22
|
||||
#: src/views/user/PasswordRecoveryForm.vue:78
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:70
|
||||
msgid "Return to login"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/identities/AccountCreationForm.vue:21
|
||||
#: src/components/identities/AccountCreationForm.vue:23
|
||||
#: src/components/identities/AccountCreationForm.vue:81
|
||||
@@ -1273,8 +1431,8 @@ msgstr ""
|
||||
msgid "Secondary email"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/layout/Navbar.vue:106 src/views/user/Security.vue:3
|
||||
#: src/components/layout/Navbar.vue:221
|
||||
#: src/components/layout/Navbar.vue:112 src/views/user/Security.vue:3
|
||||
#: src/components/layout/Navbar.vue:227
|
||||
msgid "Security"
|
||||
msgstr ""
|
||||
|
||||
@@ -1344,6 +1502,7 @@ msgstr ""
|
||||
|
||||
#: src/components/identities/AccountSenderAddresses.vue:9
|
||||
#: src/components/identities/AccountSenderAddresses.vue:2
|
||||
#: src/plugins/vee-validate.js:24
|
||||
msgid "Specify an email address"
|
||||
msgstr ""
|
||||
|
||||
@@ -1362,11 +1521,22 @@ msgstr ""
|
||||
msgid "Start typing a name here..."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/logs/MessageList.vue:10
|
||||
#: src/components/logs/MessageList.vue:43
|
||||
#: src/views/domains/Domain.vue:14
|
||||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alarms/AlarmList.vue:9 src/components/logs/MessageList.vue:11
|
||||
#: src/components/alarms/AlarmList.vue:73
|
||||
#: src/components/logs/MessageList.vue:44
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:19
|
||||
#: src/views/user/PasswordRecoveryForm.vue:15
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:17
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tools/CreationForm.vue:9
|
||||
#: src/components/tools/CreationForm.vue:32
|
||||
msgid "Summary"
|
||||
@@ -1407,12 +1577,37 @@ msgstr ""
|
||||
msgid "This page is still under construction."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/logs/MessageList.vue:11
|
||||
#: src/views/user/PasswordRecoveryForm.vue:25
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/logs/MessageList.vue:12
|
||||
#: src/components/tools/TimeSerieChart.vue:18
|
||||
#: src/components/logs/MessageList.vue:44
|
||||
#: src/components/logs/MessageList.vue:45
|
||||
msgid "To"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/Login.vue:39 src/views/user/PasswordRecoveryChangeForm.vue:62
|
||||
#: src/views/user/PasswordRecoveryForm.vue:69
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:46 src/views/Login.vue:99
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:122
|
||||
#: src/views/user/PasswordRecoveryForm.vue:115
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:94
|
||||
msgid "Too many unsuccessful attempts, please try later."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:33
|
||||
#: src/components/dmarc/DmarcSourceTable.vue:8
|
||||
#: src/components/dmarc/DmarcSourceTable.vue:3
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:151
|
||||
msgid "Total"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:37
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:85
|
||||
msgid "TOTP resent."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/domains/DomainCreationForm.vue:77
|
||||
#: src/components/domains/DomainCreationForm.vue:117
|
||||
#: src/components/domains/DomainForm.vue:89
|
||||
@@ -1421,6 +1616,14 @@ msgstr ""
|
||||
msgid "Transport"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alarms/AlarmList.vue:8 src/components/alarms/AlarmList.vue:72
|
||||
msgid "Triggered"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:40
|
||||
msgid "Trusted sources"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/user/TwoFactorAuthForm.vue:4
|
||||
msgid "Two factor authentication"
|
||||
msgstr ""
|
||||
@@ -1449,6 +1652,10 @@ msgstr ""
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/dmarc/DmarcAligmentChart.vue:43
|
||||
msgid "Unknown sources / Threats"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/identities/AccountMailboxForm.vue:30
|
||||
#: src/components/identities/AccountMailboxForm.vue:69
|
||||
msgid "unlimited"
|
||||
@@ -1478,6 +1685,15 @@ msgstr ""
|
||||
msgid "Use domain default value"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoverySmsTotpForm.vue:43
|
||||
msgid "User seems wrong, return to login or restart reset the process?"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:56
|
||||
#: src/views/user/PasswordRecoveryChangeForm.vue:116
|
||||
msgid "User unknown."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/domains/AdministratorList.vue:18
|
||||
#: src/components/identities/AccountCreationForm.vue:29
|
||||
#: src/components/identities/AccountGeneralForm.vue:19 src/views/Login.vue:9
|
||||
@@ -1517,8 +1733,8 @@ msgstr ""
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tools/TimeSerieChart.vue:52
|
||||
#: src/components/tools/TimeSerieChart.vue:110
|
||||
#: src/components/tools/TimeSerieChart.vue:51
|
||||
#: src/components/tools/TimeSerieChart.vue:109
|
||||
msgid "Week"
|
||||
msgstr ""
|
||||
|
||||
@@ -1535,8 +1751,8 @@ msgstr ""
|
||||
msgid "With mailbox"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/tools/TimeSerieChart.vue:54
|
||||
#: src/components/tools/TimeSerieChart.vue:112
|
||||
#: src/components/tools/TimeSerieChart.vue:53
|
||||
#: src/components/tools/TimeSerieChart.vue:111
|
||||
msgid "Year"
|
||||
msgstr ""
|
||||
|
||||
@@ -1593,6 +1809,10 @@ msgstr ""
|
||||
msgid "This field is required"
|
||||
msgstr ""
|
||||
|
||||
#: src/plugins/vee-validate.js:33
|
||||
#: src/plugins/vee-validate.js:37
|
||||
msgid "Invalid password"
|
||||
msgstr ""
|
||||
|
||||
#: src/api/repository.js:38
|
||||
msgid "You are throttled, please try later."
|
||||
msgstr ""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,29 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
|
||||
import polib
|
||||
|
||||
|
||||
LOCALES = [
|
||||
"br",
|
||||
"cs",
|
||||
"de",
|
||||
"el",
|
||||
"es",
|
||||
"fi",
|
||||
"fr",
|
||||
"it",
|
||||
"ja",
|
||||
"nl",
|
||||
"pt",
|
||||
"pt-br",
|
||||
"pl",
|
||||
"po",
|
||||
"ru",
|
||||
"sv",
|
||||
"tr",
|
||||
"zh-hant",
|
||||
]
|
||||
|
||||
OLD_TRANSLATION_MODULES = [
|
||||
@@ -16,16 +35,23 @@ OLD_TRANSLATION_MODULES = [
|
||||
"maillog",
|
||||
"policyd",
|
||||
"relaydomains",
|
||||
"transport"
|
||||
"transport",
|
||||
"dmarc",
|
||||
]
|
||||
|
||||
|
||||
def merge_translations():
|
||||
for locale in LOCALES:
|
||||
new_po = polib.pofile(f"locale/{locale}/LC_MESSAGES/app.po")
|
||||
target = f"locale/{locale}/LC_MESSAGES/app.po"
|
||||
print(f"Opening {target}")
|
||||
new_po = polib.pofile(target)
|
||||
for module in OLD_TRANSLATION_MODULES:
|
||||
prefix = f"../modoboa/{module}" if module else "../modoboa"
|
||||
old_po = polib.pofile(f"{prefix}/locale/{locale}/LC_MESSAGES/django.po")
|
||||
old_file = f"{prefix}/locale/{locale}/LC_MESSAGES/django.po"
|
||||
if not os.path.exists(old_file):
|
||||
continue
|
||||
print(f"Opening {old_file}")
|
||||
old_po = polib.pofile(old_file)
|
||||
for entry in new_po:
|
||||
old_entry = old_po.find(entry.msgid)
|
||||
if old_entry:
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"@mdi/font": "^5.9.55",
|
||||
"apexcharts": "^3.25.0",
|
||||
"core-js": "^3.6.5",
|
||||
"debounce": "^1.2.1",
|
||||
"js-cookie": "^2.2.1",
|
||||
"luxon": "^1.28.1",
|
||||
"vee-validate": "^3.4.5",
|
||||
|
||||
@@ -13,6 +13,12 @@ export default {
|
||||
getDomainDNSDetail (domainId) {
|
||||
return repository.get(`/${domainResource}/${domainId}/dns_detail/`)
|
||||
},
|
||||
getDomainDmarcAlignment (domainId, period) {
|
||||
return repository.get(
|
||||
`${domainResource}/${domainId}/dmarc/alignment_stats/`,
|
||||
{ params: { period } }
|
||||
)
|
||||
},
|
||||
getDomainAliases (domain) {
|
||||
let url = `/${domainAliasResource}/`
|
||||
if (domain !== undefined) {
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
<script>
|
||||
import alarms from '@/api/alarms'
|
||||
|
||||
import debounce from 'debounce'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
@@ -104,6 +104,9 @@ export default {
|
||||
mounted () {
|
||||
this.fetchAlarms()
|
||||
},
|
||||
created () {
|
||||
this.fetchAlarms = debounce(this.fetchAlarms, 500)
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
handler () {
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
<template>
|
||||
<div v-if="alignments">
|
||||
<v-card>
|
||||
<v-toolbar dense elevation="0" class="mr-2">
|
||||
<v-toolbar-title><translate>Alignment</translate></v-toolbar-title>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
icon
|
||||
x-small
|
||||
@click="previousWeek"
|
||||
>
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</v-btn>
|
||||
<span class="mx-2">{{ weekStart.toLocaleString() }} - {{ weekEnd.toLocaleString() }}</span>
|
||||
<v-btn
|
||||
icon
|
||||
x-small
|
||||
@click="nextWeek"
|
||||
>
|
||||
<v-icon>mdi-arrow-right</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="5">
|
||||
<apexchart
|
||||
v-if="series"
|
||||
type="pie"
|
||||
height="350"
|
||||
:options="options"
|
||||
:series="series"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="7">
|
||||
<v-row>
|
||||
<v-col
|
||||
v-for="box in boxes"
|
||||
:key="box.key"
|
||||
cols="6"
|
||||
>
|
||||
<v-sheet
|
||||
outlined
|
||||
:color="box.color"
|
||||
rounded
|
||||
>
|
||||
<v-card
|
||||
outlined
|
||||
class="pa-10 text-center"
|
||||
>
|
||||
<span :class="'text-h4 ' + getTextColors(box.color)">{{ stats[box.key] }}</span><br>
|
||||
<span class="text-subtitle-1">{{ box.label }}</span>
|
||||
</v-card>
|
||||
</v-sheet>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<v-expansion-panels
|
||||
v-model="panel"
|
||||
class="mt-2"
|
||||
>
|
||||
<v-expansion-panel>
|
||||
<v-expansion-panel-header>
|
||||
<translate>Detail</translate>
|
||||
</v-expansion-panel-header>
|
||||
<v-expansion-panel-content>
|
||||
<dmarc-source-table
|
||||
:title="'Trusted sources'|translate"
|
||||
color="green"
|
||||
:total="stats.aligned"
|
||||
:sources="alignments.aligned"
|
||||
/>
|
||||
<dmarc-source-table
|
||||
:title="'Partially trusted sources / Forwarders'|translate"
|
||||
color="orange"
|
||||
:total="stats.trusted"
|
||||
:sources="alignments.trusted"
|
||||
class="mt-4"
|
||||
/>
|
||||
<dmarc-source-table
|
||||
:title="'Forwarders with ARC'|translate"
|
||||
color="blue"
|
||||
:total="stats.forwarded"
|
||||
:sources="alignments.forwarded"
|
||||
class="mt-4"
|
||||
/>
|
||||
<dmarc-source-table
|
||||
:title="'Unknown sources / Threats'|translate"
|
||||
color="red"
|
||||
:total="stats.failed"
|
||||
:sources="alignments.failed"
|
||||
class="mt-4"
|
||||
/>
|
||||
</v-expansion-panel-content>
|
||||
</v-expansion-panel>
|
||||
</v-expansion-panels>
|
||||
</div>
|
||||
<div v-else>
|
||||
<v-alert
|
||||
v-if="dmarcDisabled"
|
||||
type="info"
|
||||
outlined
|
||||
prominent
|
||||
border="left"
|
||||
class="mt-6"
|
||||
>
|
||||
<translate tag="div">
|
||||
DMARC support does not seem to be enabled for this domain.</translate>
|
||||
<translate tag="div">
|
||||
If you configured it recently, please wait for the first report to be received and processed.
|
||||
</translate>
|
||||
</v-alert>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import colors from 'vuetify/lib/util/colors'
|
||||
import DmarcSourceTable from './DmarcSourceTable'
|
||||
import domainsApi from '@/api/domains'
|
||||
import { DateTime } from 'luxon'
|
||||
import VueApexCharts from 'vue-apexcharts'
|
||||
|
||||
const order = ['aligned', 'trusted', 'forwarded', 'failed']
|
||||
|
||||
export default {
|
||||
components: {
|
||||
apexchart: VueApexCharts,
|
||||
DmarcSourceTable
|
||||
},
|
||||
props: {
|
||||
domain: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
options: {
|
||||
colors: [colors.green.lighten2, colors.orange.lighten2, colors.blue.lighten2, colors.red.lighten2],
|
||||
labels: [
|
||||
this.$gettext('Fully aligned'),
|
||||
this.$gettext('Partially aligned'),
|
||||
this.$gettext('Forwarded'),
|
||||
this.$gettext('Failed')
|
||||
],
|
||||
legend: {
|
||||
position: 'bottom'
|
||||
}
|
||||
},
|
||||
alignments: null,
|
||||
boxes: [
|
||||
{ key: 'total', label: this.$gettext('Total'), color: 'primary lighten-2' },
|
||||
{ key: 'aligned', label: this.$gettext('Fully aligned'), color: 'green lighten-2' },
|
||||
{ key: 'trusted', label: this.$gettext('Partially aligned'), color: 'orange lighten-2' },
|
||||
{ key: 'forwarded', label: this.$gettext('Forwarded'), color: 'blue lighten-2' },
|
||||
{ key: 'failed', label: this.$gettext('Failed'), color: 'red lighten-2' }
|
||||
],
|
||||
currentWeek: 0,
|
||||
currentYear: 0,
|
||||
dmarcDisabled: false,
|
||||
loading: false,
|
||||
panel: null,
|
||||
series: [],
|
||||
stats: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
weekStart () {
|
||||
const dt = DateTime.fromObject({
|
||||
weekYear: this.currentYear,
|
||||
weekNumber: this.currentWeek
|
||||
})
|
||||
return dt.startOf('week')
|
||||
},
|
||||
weekEnd () {
|
||||
const dt = DateTime.fromObject({
|
||||
weekYear: this.currentYear,
|
||||
weekNumber: this.currentWeek
|
||||
})
|
||||
return dt.endOf('week')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getTextColors (value) {
|
||||
let result = ''
|
||||
for (const color of value.split(' ')) {
|
||||
if (result !== '') {
|
||||
result += ' '
|
||||
}
|
||||
if (color.startsWith('lighten')) {
|
||||
result += 'text--' + color
|
||||
} else {
|
||||
result += color + '--text'
|
||||
}
|
||||
}
|
||||
return result
|
||||
},
|
||||
nextWeek () {
|
||||
if (this.currentWeek === 52) {
|
||||
this.currentYear += 1
|
||||
this.currentWeek = 1
|
||||
} else {
|
||||
this.currentWeek += 1
|
||||
}
|
||||
},
|
||||
previousWeek () {
|
||||
if (this.currentWeek === 1) {
|
||||
this.currentYear -= 1
|
||||
this.currentWeek = 52
|
||||
} else {
|
||||
this.currentWeek -= 1
|
||||
}
|
||||
},
|
||||
fetchAlignmentStats () {
|
||||
if (this.loading) {
|
||||
return
|
||||
}
|
||||
const period = `${this.currentYear}-${this.currentWeek}`
|
||||
this.loading = true
|
||||
domainsApi.getDomainDmarcAlignment(this.domain.pk, period).then(resp => {
|
||||
this.loading = false
|
||||
if (resp.status === 204) {
|
||||
this.dmarcDisabled = true
|
||||
return
|
||||
}
|
||||
this.stats = { total: 0 }
|
||||
this.alignments = resp.data
|
||||
this.series = []
|
||||
for (const key of order) {
|
||||
let total = 0
|
||||
for (const name in resp.data[key]) {
|
||||
for (const ip in resp.data[key][name]) {
|
||||
total += resp.data[key][name][ip].total
|
||||
}
|
||||
}
|
||||
this.stats.total += total
|
||||
this.stats[key] = total
|
||||
this.series.push(total)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
const now = DateTime.now()
|
||||
this.currentYear = now.year
|
||||
this.currentWeek = now.weekNumber
|
||||
},
|
||||
mounted () {
|
||||
this.fetchAlignmentStats()
|
||||
},
|
||||
watch: {
|
||||
currentWeek () {
|
||||
this.fetchAlignmentStats()
|
||||
},
|
||||
currentYear () {
|
||||
this.fetchAlignmentStats()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-h6">{{ title }} <span :class="`${color}--text text--lighten-2`">{{ total }}</span></div>
|
||||
<v-simple-table>
|
||||
<tbody>
|
||||
<template v-for="(source, name) in sources">
|
||||
<tr :key="name">
|
||||
<th width="40%">{{ name }}</th>
|
||||
<th><translate>Total</translate></th>
|
||||
<th>SPF</th>
|
||||
<th>DKIM</th>
|
||||
</tr>
|
||||
<tr v-for="(counters, ip) in source" :key="ip">
|
||||
<td>{{ ip }}</td>
|
||||
<td>{{ counters.total }}</td>
|
||||
<td>
|
||||
<v-avatar
|
||||
color="green lighten-2"
|
||||
size="24"
|
||||
>
|
||||
<span class="white--text">{{ counters.spf.success }}</span>
|
||||
</v-avatar>
|
||||
<v-avatar
|
||||
color="red lighten-2 ml-1"
|
||||
size="24"
|
||||
>
|
||||
<span class="white--text">{{ counters.spf.failure }}</span>
|
||||
</v-avatar>
|
||||
</td>
|
||||
<td>
|
||||
<v-avatar
|
||||
color="green lighten-2"
|
||||
size="24"
|
||||
>
|
||||
<span class="white--text">{{ counters.dkim.success }}</span>
|
||||
</v-avatar>
|
||||
<v-avatar
|
||||
color="red lighten-2 ml-1"
|
||||
size="24"
|
||||
>
|
||||
<span class="white--text">{{ counters.dkim.failure }}</span>
|
||||
</v-avatar>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</v-simple-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: String,
|
||||
color: String,
|
||||
total: Number,
|
||||
sources: Object
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<script>
|
||||
import logs from '@/api/logs'
|
||||
|
||||
import debounce from 'debounce'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
@@ -80,6 +80,9 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.fetchLogs = debounce(this.fetchLogs, 500)
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
handler () {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
<script>
|
||||
import logs from '@/api/logs'
|
||||
import debounce from 'debounce'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
@@ -70,6 +71,9 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.fetchMessages = debounce(this.fetchMessages, 500)
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
handler () {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -13,6 +13,7 @@
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
vid="code"
|
||||
name="code"
|
||||
rules="required"
|
||||
>
|
||||
<v-row>
|
||||
@@ -24,13 +25,14 @@
|
||||
:error-messages="errors"
|
||||
:hint="'Enter the code from the two-factor app on your mobile device. If you have lost your device, you may enter one of your recovery codes.'|translate"
|
||||
persistent-hint
|
||||
@finish="verifyCode"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</validation-provider>
|
||||
</validation-observer>
|
||||
<div class="d-flex justify-center mt-6">
|
||||
<v-btn class="flex-grow-1" color="primary" large @click="verifyCode">
|
||||
<v-btn class="flex-grow-1" color="primary" large @click="verifyCode" :loading="loading">
|
||||
<translate>Verify code</translate>
|
||||
</v-btn>
|
||||
</div>
|
||||
@@ -46,7 +48,8 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
code: null,
|
||||
errors: {}
|
||||
errors: {},
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -55,6 +58,7 @@ export default {
|
||||
if (!isValid) {
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
account.verifyTFACode(this.code).then(resp => {
|
||||
Cookies.set('token', resp.data.access, { sameSite: 'strict' })
|
||||
Cookies.set('refreshToken', resp.data.refresh, { sameSite: 'strict' })
|
||||
@@ -63,6 +67,7 @@ export default {
|
||||
})
|
||||
}).catch(error => {
|
||||
this.$refs.observer.setErrors(error.response.data)
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,49 +6,77 @@
|
||||
<v-icon>mdi-circle-edit-outline</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
<v-layout>
|
||||
<v-row>
|
||||
<v-col cols="6">
|
||||
<domain-summary :domain="domain" />
|
||||
<div class="mt-4" />
|
||||
<administrator-list
|
||||
|
||||
<v-tabs
|
||||
v-model="tab"
|
||||
>
|
||||
<v-tab>
|
||||
<translate>General</translate>
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
<translate>Statistics</translate>
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
<translate>DMARC</translate>
|
||||
</v-tab>
|
||||
<v-tabs-items
|
||||
v-model="tab"
|
||||
>
|
||||
<v-tab-item>
|
||||
<v-layout class="pa-2">
|
||||
<v-row>
|
||||
<v-col cols="6">
|
||||
<domain-summary :domain="domain" />
|
||||
<div class="mt-4" />
|
||||
<administrator-list
|
||||
:domain="domain"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<dns-detail v-model="domain" />
|
||||
<div class="mt-4" />
|
||||
<resources
|
||||
v-if="limitsConfig.params && limitsConfig.params.enable_domain_limits && domain.resources && domain.resources.length"
|
||||
:resources="domain.resources"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-layout>
|
||||
</v-tab-item>
|
||||
<v-tab-item>
|
||||
<v-layout class="pa-2">
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="12">
|
||||
<time-serie-chart
|
||||
v-if="domain.name"
|
||||
:domain="domain"
|
||||
graphic-set="mailtraffic"
|
||||
graphic-name="averagetraffic"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<time-serie-chart
|
||||
v-if="domain.name"
|
||||
:domain="domain"
|
||||
graphic-set="mailtraffic"
|
||||
graphic-name="averagetrafficsize"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-layout>
|
||||
</v-tab-item>
|
||||
<v-tab-item>
|
||||
<dmarc-aligment-chart
|
||||
:domain="domain"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<dns-detail v-model="domain" />
|
||||
<div class="mt-4" />
|
||||
<resources
|
||||
v-if="limitsConfig.params && limitsConfig.params.enable_domain_limits && domain.resources && domain.resources.length"
|
||||
:resources="domain.resources"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-layout>
|
||||
<v-layout>
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="12">
|
||||
<time-serie-chart
|
||||
v-if="domain.name"
|
||||
:domain="domain"
|
||||
graphic-set="mailtraffic"
|
||||
graphic-name="averagetraffic"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<time-serie-chart
|
||||
v-if="domain.name"
|
||||
:domain="domain"
|
||||
graphic-set="mailtraffic"
|
||||
graphic-name="averagetrafficsize"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-layout>
|
||||
<v-dialog v-model="showEditForm"
|
||||
persistent
|
||||
max-width="800px"
|
||||
>
|
||||
</v-tab-item>
|
||||
</v-tabs-items>
|
||||
</v-tabs>
|
||||
<v-dialog
|
||||
v-model="showEditForm"
|
||||
persistent
|
||||
max-width="800px"
|
||||
>
|
||||
<domain-form :domain="domain" @close="showEditForm = false" />
|
||||
</v-dialog>
|
||||
</div>
|
||||
@@ -57,6 +85,7 @@
|
||||
<script>
|
||||
import domains from '@/api/domains'
|
||||
import AdministratorList from '@/components/domains/AdministratorList'
|
||||
import DmarcAligmentChart from '@/components/dmarc/DmarcAligmentChart'
|
||||
import DNSDetail from '@/components/domains/DNSDetail'
|
||||
import DomainForm from '@/components/domains/DomainForm'
|
||||
import DomainSummary from '@/components/domains/DomainSummary'
|
||||
@@ -68,6 +97,7 @@ export default {
|
||||
components: {
|
||||
AdministratorList,
|
||||
'dns-detail': DNSDetail,
|
||||
DmarcAligmentChart,
|
||||
DomainForm,
|
||||
DomainSummary,
|
||||
Resources,
|
||||
@@ -78,7 +108,8 @@ export default {
|
||||
domain: { pk: this.$route.params.id },
|
||||
limitsConfig: {},
|
||||
showEditForm: false,
|
||||
showAdminList: false
|
||||
showAdminList: false,
|
||||
tab: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -98,4 +129,7 @@ export default {
|
||||
.v-toolbar {
|
||||
background-color: #f7f8fa !important;
|
||||
}
|
||||
.v-tabs-items {
|
||||
background-color: #f7f8fa !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3002,6 +3002,11 @@ de-indent@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||
integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==
|
||||
|
||||
debounce@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5"
|
||||
integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==
|
||||
|
||||
debug@2.6.9, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,20 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Irriep Nala Novram <allannkorh@yahoo.fr>, 2019
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2019-03-08 09:15+0000\n"
|
||||
"Last-Translator: Irriep Nala Novram <allannkorh@yahoo.fr>\n"
|
||||
"Language-Team: Breton (http://www.transifex.com/tonio/modoboa/language/br/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Breton (https://www.transifex.com/tonio/teams/13749/br/)\n"
|
||||
"Language: br\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -22,19 +25,19 @@ msgstr ""
|
||||
"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 "
|
||||
"&& n % 1000000 == 0) ? 3 : 4);\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Domani ebet ken da ziskouez"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Na zilamit ket ar c'havlec'h domanioù"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "An oberiadenn-mañ a zilamo an HOLL roadennoù stag ouzh an domani-mañ."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -42,18 +45,24 @@ msgstr ""
|
||||
"An oberiadenn-mañ a zilamo an HOLL roadennoù stag ouzh an domani-mañ, paneve "
|
||||
"ar c'hontoù."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Kota ebet ken da ziskouez"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Kota ebet ken da ziskouez"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Merour domani ebet termenet"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Identelezh ebet ken da ziskouez"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Na zilamit ket kavlec'h ar voest-posteloù"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,21 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Miroslav Abrahám <miris@kunago.com>, 2013,2015
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:50+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/tonio/"
|
||||
"modoboa/language/cs_CZ/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Czech (Czech Republic) (https://www.transifex.com/tonio/"
|
||||
"teams/13749/cs_CZ/)\n"
|
||||
"Language: cs_CZ\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -20,37 +23,43 @@ msgstr ""
|
||||
"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"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Žádná další doména k zobrazení"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Nemazat adresář domény"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Tento krok odstraní VŠECHNA data související s touto doménou."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
"Tento krok odstraní VŠECHNA data související s touto doménou, vyjma účtů."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Žádná další kvóta k zobrazení"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Žádná další kvóta k zobrazení"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Není určen správce domény"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Žádná další identita k zobrazení"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Nemazat adresář schránky"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,37 +1,39 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Arvedui <arvedui@posteo.de>, 2014
|
||||
# Patrick Koetter <p@state-of-mind.de>, 2010
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:50+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: German (http://www.transifex.com/tonio/modoboa/language/de/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: German (https://www.transifex.com/tonio/teams/13749/de/)\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Keine weiteren Domains"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Verzeichnis der Domain nicht löschen"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Diese Aktion wird ALLE mit der Domain verbundenen Daten löschen."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -39,18 +41,24 @@ msgstr ""
|
||||
"Diese Aktion wird ALLE mit der Domain verbundenen Daten, außer Mailkonten, "
|
||||
"löschen."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Keine weiteren Quotas"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Keine weiteren Quotas"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Domain-Administrator fehlt"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Keine weiteren Identitäten"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Verzeichnis der Mailbox nicht löschen"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,40 +1,42 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Giannis Kapetanakis <bilias@edu.physics.uoc.gr>, 2016
|
||||
# Kostas Moumouris <moumouriskostas@gmail.com>, 2017
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-10-05 20:01+0000\n"
|
||||
"Last-Translator: Kostas Moumouris <moumouriskostas@gmail.com>\n"
|
||||
"Language-Team: Greek (Greece) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/el_GR/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Greek (Greece) (https://www.transifex.com/tonio/teams/13749/"
|
||||
"el_GR/)\n"
|
||||
"Language: el_GR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Δεν υπάρχουν άλλα domains για εμφάνιση"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Να μην διαγραφεί ο κατάλογος αρχείων του domain "
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr ""
|
||||
"Αυτή η λειτουργία θα καταργήσει ΟΛΑ τα δεδομένα που σχετίζονται με αυτό το "
|
||||
"domain."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -42,18 +44,24 @@ msgstr ""
|
||||
"Αυτή η λειτουργία θα καταργήσει όλα τα δεδομένα που σχετίζονται με αυτό το "
|
||||
"domain, εκτός από τους λογαριασμούς χρηστών."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Δεν υπάρχει κανένα quota"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Δεν υπάρχει κανένα quota"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Δεν έχει οριστεί διαχειριστής domain"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Δεν υπάρχουν άλλες ταυτότητες για εμφάνιση"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Να μην διαγραφεί ο κατάλογος αρχείων του γραμματοκιβωτίου "
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,36 +17,40 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr ""
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr ""
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr ""
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr ""
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
msgid "No more log to show"
|
||||
msgstr ""
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr ""
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr ""
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr ""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,39 +1,40 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Pedro Gracia <lasarux@neuroomante.com>, 2011,2013
|
||||
# Pedro Gracia <pedro.gracia@impulzia.com>, 2010-2011
|
||||
# samuel santos <sags9201@gmail.com>, 2017
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-02-21 00:55+0000\n"
|
||||
"Last-Translator: samuel santos <sags9201@gmail.com>\n"
|
||||
"Language-Team: Spanish (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"es/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/tonio/teams/13749/es/)\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? "
|
||||
"1 : 2;\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Sin dominios que mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "No eleminar el directorio del dominio"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Esta operación eliminará TODOS los datos asociados a este dominio."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -41,18 +42,24 @@ msgstr ""
|
||||
"Esta operación eliminará todos los datos asociados a este dominio, excepto "
|
||||
"las cuentas."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Sin cuota para mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Sin cuota para mostrar"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "No hay un administrador de dominio definido"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Sin identidades que mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "No eliminar el directorio del mailbox"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-02-17 16:48+0100\n"
|
||||
"PO-Revision-Date: 2023-02-17 20:10+0200\n"
|
||||
"Last-Translator: Ossi Mantylahti <ossiman@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: fi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Ei enää verkkotunnusta näytettäväksi"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Älä poista verkkotunnuksen hakemistoa"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr ""
|
||||
"Tämä toiminto poistaa KAIKKI tähän verkkotunnukseen liittyvät tiedot."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
"Tämä toiminto poistaa kaikki tähän verkkotunnukseen liittyvät tiedot "
|
||||
"lukuun ottamatta tilejä."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
msgid "No more quota to show"
|
||||
msgstr "Ei enää kiintiöitä näytettäväksi"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Verkkotunnuksen ylläpitäjää ei ole määritetty"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
msgid "No more identity to show"
|
||||
msgstr "Ei enää identiteettiä näytettäväksi"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Älä poista postilaatikkohakemistoa"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +1,58 @@
|
||||
# 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>, 2023
|
||||
# Christophe CHAUVET <christophe.chauvet@gmail.com>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:50+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2015-06-03 15:50+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: French (http://www.transifex.com/tonio/modoboa/language/fr/)\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Plus de domaine à afficher"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Ne pas supprimer le répertoire du domaine"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Cette opération supprimera TOUTES les données associées à ce domaine."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
"Cette opération supprimera toutes les données associées à ce domaine à "
|
||||
"l'exception des comptes."
|
||||
msgstr "Cette opération supprimera toutes les données associées à ce domaine à l'exception des comptes."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Plus de quota à afficher"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
msgid "No more log to show"
|
||||
msgstr "Plus aucun journal à afficher"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Aucun administrateur de domaine défini"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Plus d'identité à afficher"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Ne pas supprimer le répertoire de la boite aux lettres"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,37 +1,40 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Rocco <mors10@hotmail.com>, 2015
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:50+0000\n"
|
||||
"Last-Translator: Rocco <mors10@hotmail.com>\n"
|
||||
"Language-Team: Italian (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"it/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Italian (https://www.transifex.com/tonio/teams/13749/it/)\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? "
|
||||
"1 : 2;\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Non ci sono altri domini da mostrare"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Non eliminare la cartella dei domini"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Questa operazione eliminerà TUTTI i dati associati a questo dominio."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -39,18 +42,24 @@ msgstr ""
|
||||
"Questa operazione eliminerà tutti i dati associati a questo dominio tranne "
|
||||
"gli account"
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Non ci sono altre quote da mostrare"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Non ci sono altre quote da mostrare"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Non è stato definito un amministratore di dominio"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Non ci sono altre identità da mostrare"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Non eliminare la cartella della casella posta"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,37 +1,40 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# cwatanab <chihiro.watanabe@live.jp>, 2016
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2016-06-07 07:01+0000\n"
|
||||
"Last-Translator: cwatanab <chihiro.watanabe@live.jp>\n"
|
||||
"Language-Team: Japanese (Japan) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/ja_JP/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Japanese (Japan) (https://www.transifex.com/tonio/teams/13749/"
|
||||
"ja_JP/)\n"
|
||||
"Language: ja_JP\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "表示するドメインはありません。"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "ドメインディレクトリを削除しないでください"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "この操作は、このドメインに関連するすべてのデータを削除します。"
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -39,18 +42,24 @@ msgstr ""
|
||||
"この操作は、アカウントを除いたこのドメインに関連するすべてのデータを削除しま"
|
||||
"す。"
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "表示するクォータはありません"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "表示するクォータはありません"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "ドメイン管理者が指定されていません"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "表示する ID はありません"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "メールボックスディレクトリを削除しないでください"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,58 +1,60 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
#
|
||||
# Translators:
|
||||
# Harrie v.d. Vegt <hvdvegt@gmail.com>, 2016
|
||||
# J Rosier <vertalen@tagora.nl>, 2023
|
||||
# TuxBrother <vrijwilligerswerk@wij.rs>, 2014
|
||||
# Tuxis Internet Engineering V.O.F. <info@tuxis.nl>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-23 21:20+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"
|
||||
"Language: nl_NL\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2015-06-03 15:50+0000\n"
|
||||
"Last-Translator: J Rosier <vertalen@tagora.nl>, 2023\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"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Geen domeinen meer om weer te geven"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "De map van dit domein niet verwijderen"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Deze actie zal ALLE data verwijderen die bij dit domein hoort."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
"Deze actie zal alle data die bij dit domein hoort verwijderen, behalve de "
|
||||
"accounts."
|
||||
msgstr "Deze actie zal alle data die bij dit domein hoort verwijderen, behalve de accounts."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Geen quotum meer om weer te geven"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
msgid "No more log to show"
|
||||
msgstr "Geen logbestand meer om weer te geven"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Geen domeinbeheerder toegewezen"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Geen identiteiten meer om weer te geven"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Verwijder de map van deze mailbox niet"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,21 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# sin88 <sin@sin.waw.pl>, 2016
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:50+0000\n"
|
||||
"Last-Translator: sin88 <sin@sin.waw.pl>\n"
|
||||
"Language-Team: Polish (Poland) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/pl_PL/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Polish (Poland) (https://www.transifex.com/tonio/teams/13749/"
|
||||
"pl_PL/)\n"
|
||||
"Language: pl_PL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -21,37 +24,43 @@ msgstr ""
|
||||
"%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"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Brak domen do pokazania"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Nie usuwaj katalogu domeny"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Ta operacja usunie WSZYSTKIE dane powiązane z tą domeną."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
"Ta operacja usunie wszystkie dane powiązana z tą domeną za wyjątkiem kont."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Brak limitów do wyświetlenia"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Brak limitów do wyświetlenia"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Nie zdefiniowano administratora domeny"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Brak tożsamości do wyświetlenia"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Nie usuwaj katalogu skrzynki pocztowej"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,37 +1,41 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Paulino Michelazzo <paulino@michelazzo.com.br>, 2014
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-23 21:20+0000\n"
|
||||
"Last-Translator: Rafael Barretto <ch3yd@hotmail.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/pt_BR/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Portuguese (Brazil) (https://www.transifex.com/tonio/"
|
||||
"teams/13749/pt_BR/)\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % "
|
||||
"1000000 == 0 ? 1 : 2;\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Nenhum domínio a mais para mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Não remova o diretório de domínio"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Esta operação removerá TODOS os dados associados com este domínio."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -39,18 +43,24 @@ msgstr ""
|
||||
"Esta operação removerá todos os dados associados com este domínio, exceto "
|
||||
"contas."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Nenhuma quota a mais para mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Nenhuma quota a mais para mostrar"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Nenhum administrador de domínio definido"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Nenhuma identidade a mais para mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Não remova o diretório de caixas de mensagens"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,42 +1,41 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# lusitan <lusitan@hushmail.com>, 2013
|
||||
# lusitan <lusitan@hushmail.com>, 2013
|
||||
# Mike C. <miguelmclara@gmail.com>, 2012
|
||||
# Mike C. <miguelmclara@gmail.com>, 2012
|
||||
# Mike C. <miguelmclara@gmail.com>, 2014
|
||||
# Sandra Ribeiro <sandrarib@gmail.com>, 2013
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2014-12-29 12:08+0000\n"
|
||||
"Last-Translator: Mike C. <miguelmclara@gmail.com>\n"
|
||||
"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/pt_PT/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Portuguese (Portugal) (https://www.transifex.com/tonio/"
|
||||
"teams/13749/pt_PT/)\n"
|
||||
"Language: pt_PT\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % "
|
||||
"1000000 == 0 ? 1 : 2;\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Não existem mais dominios para mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Não excluir o diretório do domínio"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Esta operação irá remover TODOS os dados associados a este domínio."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -44,18 +43,24 @@ msgstr ""
|
||||
"Esta operação irá remover TODOS os dados associados a este domínio, excepto "
|
||||
"as contas."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Não existem mais quotas para mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Não existem mais quotas para mostrar"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Não está definido nenhum administrador para o domínio"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Não existem mais identidades para mostrar"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Não excluir o diretório da caixa de correio"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,21 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Andrei-Ilie Olteanu <andrei@flashsoft.ro>, 2018
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2018-06-12 11:38+0000\n"
|
||||
"Last-Translator: Andrei-Ilie Olteanu <andrei@flashsoft.ro>\n"
|
||||
"Language-Team: Romanian (Romania) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/ro_RO/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Romanian (Romania) (https://www.transifex.com/tonio/"
|
||||
"teams/13749/ro_RO/)\n"
|
||||
"Language: ro_RO\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -20,20 +23,20 @@ msgstr ""
|
||||
"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?"
|
||||
"2:1));\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Nu mai sunt domenii de afișat"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Nu sterge directorul pentru domeniu"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr ""
|
||||
"Această operațiune va șterge toată informația asociată cu acest domeniu."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -41,18 +44,24 @@ msgstr ""
|
||||
"Această operațiune va șterge toată informația asociată cu acest domeniu, cu "
|
||||
"excepția conturilor."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Nu mai există cote de afișat"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Nu mai există cote de afișat"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Nu există configurat un administartor de domeniu"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Nu mai sunt identități de afișat"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Nu sterge directorul mailbox"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,20 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Ravil Kadyrbayev, 2015
|
||||
# Yuriy Matskanyuk <umackanuk@gmail.com>, 2018
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2018-11-27 17:54+0000\n"
|
||||
"Last-Translator: Yuriy Matskanyuk <umackanuk@gmail.com>\n"
|
||||
"Language-Team: Russian (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"ru/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Russian (https://www.transifex.com/tonio/teams/13749/ru/)\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -22,19 +23,19 @@ msgstr ""
|
||||
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
|
||||
"%100>=11 && n%100<=14)? 2 : 3);\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Нет больше доменов для показа"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Не удаляйте каталог домена"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Эта операция удалит ВСЕ данные, связанные с этим доменом."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
@@ -42,18 +43,24 @@ msgstr ""
|
||||
"Эта операция удалит ВСЕ данные, связанные с этим доменом, за исключением "
|
||||
"аккаунтов."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Нет больше квоты для показа"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Нет больше квоты для показа"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Не указан администратор домена"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Нет личности для показа"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Не удаляйте каталог почтовых ящиков"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,56 +1,58 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
#
|
||||
# Translators:
|
||||
# Joaquim Homrighausen <joho@boojam.se>, 2023
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2013,2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:50+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Swedish (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"sv/)\n"
|
||||
"Language: sv\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2015-06-03 15:50+0000\n"
|
||||
"Last-Translator: Joaquim Homrighausen <joho@boojam.se>, 2023\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"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Inga fler domäner att visa"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Radera inte domän katalog"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Denna åtgärd kommer radera ALL data associerad med den här domänen."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr ""
|
||||
"Den här operationen raderar all data som är associerad med denna domän, "
|
||||
"förutom konton."
|
||||
msgstr "Den här operationen raderar all data som är associerad med denna domän, förutom konton."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Ingen mer kvota att visa"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
msgid "No more log to show"
|
||||
msgstr "Inga fler logghändelser finns att visa"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "Ingen domänadministratör definierad"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Inga fler konton att visa"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Radera inte brevlådans katalog"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +1,63 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# Ediz Duman <neps1192@gmail.com>, 2016
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:50+0000\n"
|
||||
"Last-Translator: Ediz Duman <neps1192@gmail.com>\n"
|
||||
"Language-Team: Turkish (Turkey) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/tr_TR/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Turkish (Turkey) (https://www.transifex.com/tonio/teams/13749/"
|
||||
"tr_TR/)\n"
|
||||
"Language: tr_TR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "Gösterilecek başka domain yok"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "Domain dizini silmeyin"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "Bu işlem, bu domain ilişkili TÜM verileri kaldıracaktır."
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr "Bu işlem hesap dışında bu domain ilişkili tüm verileri kaldıracaktır."
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "Gösterilecek kota yok"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "Gösterilecek kota yok"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "domain yöneticisi tanımlanmadı"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "Gösterilecek daha fazla kimlik yok"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "Posta kutusu dizini silmeyin"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,55 +1,63 @@
|
||||
# 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.
|
||||
#
|
||||
# Translators:
|
||||
# akong <akong@aspa.idv.tw>, 2018
|
||||
# Radium <ztl8702@126.com>, 2017
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2023
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-09 16:48+0100\n"
|
||||
"PO-Revision-Date: 2018-06-29 00:40+0000\n"
|
||||
"Last-Translator: akong <akong@aspa.idv.tw>\n"
|
||||
"Language-Team: Chinese (Taiwan) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/zh_TW/)\n"
|
||||
"POT-Creation-Date: 2023-02-22 18:52+0100\n"
|
||||
"PO-Revision-Date: 2023-02-22 16:16+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>, 2023\n"
|
||||
"Language-Team: Chinese (Taiwan) (https://www.transifex.com/tonio/teams/13749/"
|
||||
"zh_TW/)\n"
|
||||
"Language: zh_TW\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: admin/static/admin/js/admin.js:129 admin/static/admin/js/admin.js:174
|
||||
#: static/admin/js/admin.js:129 static/admin/js/admin.js:174
|
||||
msgid "No more domain to show"
|
||||
msgstr "無更多網域可展示"
|
||||
|
||||
#: admin/static/admin/js/admin.js:149
|
||||
#: static/admin/js/admin.js:149
|
||||
msgid "Do not delete domain directory"
|
||||
msgstr "不可以刪除網域目錄"
|
||||
|
||||
#: admin/static/admin/js/admin.js:151
|
||||
#: static/admin/js/admin.js:151
|
||||
msgid "This operation will remove ALL data associated to this domain."
|
||||
msgstr "這個操作將會刪除所有這個網域有關的資料。"
|
||||
|
||||
#: admin/static/admin/js/admin.js:152
|
||||
#: static/admin/js/admin.js:152
|
||||
msgid ""
|
||||
"This operation will remove all data associated to this domain, excepting "
|
||||
"accounts."
|
||||
msgstr "這個操作將會刪除所有這個網域有關的資料,除了帳號。"
|
||||
|
||||
#: admin/static/admin/js/admin.js:177 admin/static/admin/js/admin.js:433
|
||||
#: static/admin/js/admin.js:177 static/admin/js/admin.js:436
|
||||
msgid "No more quota to show"
|
||||
msgstr "沒有配額可能顯示"
|
||||
|
||||
#: admin/static/admin/js/admin.js:306
|
||||
#: static/admin/js/admin.js:180
|
||||
#, fuzzy
|
||||
#| msgid "No more quota to show"
|
||||
msgid "No more log to show"
|
||||
msgstr "沒有配額可能顯示"
|
||||
|
||||
#: static/admin/js/admin.js:309
|
||||
msgid "No domain administrator defined"
|
||||
msgstr "網域管理員未指定"
|
||||
|
||||
#: admin/static/admin/js/admin.js:362 admin/static/admin/js/admin.js:430
|
||||
#: static/admin/js/admin.js:365 static/admin/js/admin.js:433
|
||||
msgid "No more identity to show"
|
||||
msgstr "沒有身份可以顯示"
|
||||
|
||||
#: admin/static/admin/js/admin.js:404
|
||||
#: static/admin/js/admin.js:407
|
||||
msgid "Do not delete mailbox directory"
|
||||
msgstr "不可能刪除郵件目錄"
|
||||
|
||||
@@ -204,6 +204,25 @@ class AccountViewSetTestCase(ModoAPITestCase):
|
||||
resp = self.client.post(url)
|
||||
self.assertEqual(resp.status_code, 201)
|
||||
|
||||
def test_failed_api_token(self):
|
||||
"""Simulate a failed login attempt and check that it is logged."""
|
||||
|
||||
url = reverse("v2:token_obtain_pair")
|
||||
data = {
|
||||
"username": "clearly_non_existent_user",
|
||||
"password": "password"
|
||||
}
|
||||
|
||||
with self.assertLogs(logger='modoboa.auth', level='WARNING') as log:
|
||||
|
||||
resp = self.client.post(url, data, format="json")
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
self.assertIn(
|
||||
"WARNING:modoboa.auth:Failed connection attempt from '127.0.0.1'"
|
||||
" as user 'clearly_non_existent_user'",
|
||||
log.output
|
||||
)
|
||||
|
||||
|
||||
class PasswordResetTestCase(AccountViewSetTestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -10,8 +10,9 @@ from django.contrib.auth import login
|
||||
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from rest_framework import response, status
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
from rest_framework_simplejwt import views as jwt_views
|
||||
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
|
||||
from rest_framework_simplejwt.exceptions import InvalidToken
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from modoboa.core.password_hashers import get_password_hasher
|
||||
@@ -28,7 +29,7 @@ logger = logging.getLogger("modoboa.auth")
|
||||
|
||||
def delete_cache_key(class_target, throttles, request):
|
||||
"""Attempt to delete cache key from throttling on login/password reset success."""
|
||||
|
||||
|
||||
for throttle in throttles:
|
||||
if type(throttle) == class_target:
|
||||
throttle.reset_cache(request)
|
||||
@@ -44,11 +45,11 @@ class TokenObtainPairView(jwt_views.TokenObtainPairView):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
try:
|
||||
serializer.is_valid(raise_exception=True)
|
||||
except TokenError as e:
|
||||
except AuthenticationFailed as e:
|
||||
logger.warning(
|
||||
_("Failed connection attempt from '%s' as user '%s'"),
|
||||
request.META["REMOTE_ADDR"],
|
||||
escape(serializer.data["username"])
|
||||
escape(serializer.initial_data["username"])
|
||||
)
|
||||
raise InvalidToken(e.args[0])
|
||||
|
||||
@@ -133,7 +134,7 @@ class DefaultPasswordResetView(EmailPasswordResetView):
|
||||
serializer.is_valid(raise_exception=True)
|
||||
except serializers.NoSMSAvailable:
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
|
||||
# SMS response
|
||||
return response.Response({"type": "sms"}, 200)
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ MODOBOA_APPS = (
|
||||
'modoboa.policyd',
|
||||
'modoboa.maillog',
|
||||
'modoboa.pdfcredentials',
|
||||
'modoboa.dmarc',
|
||||
# Modoboa extensions here.
|
||||
{% for extension in extensions %} '{{ extension }}',
|
||||
{% endfor %}
|
||||
|
||||
@@ -28,6 +28,7 @@ LANGUAGES = (
|
||||
("en", u"english"),
|
||||
("el", u"ελληνικά"),
|
||||
("es", u"español"),
|
||||
("fi", "Suomalainen"),
|
||||
("fr", u"français"),
|
||||
("it", u"italiano"),
|
||||
("ja", u"日本の"),
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.16 on 2023-02-23 14:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0023_auto_20221012_0911'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='language',
|
||||
field=models.CharField(choices=[('br', 'breton'), ('cs', 'čeština'), ('de', 'deutsch'), ('en', 'english'), ('el', 'ελληνικά'), ('es', 'español'), ('fi', 'Suomalainen'), ('fr', 'français'), ('it', 'italiano'), ('ja', '日本の'), ('nl', 'nederlands'), ('pt', 'português'), ('pt-br', 'português (BR)'), ('pl', 'polski'), ('ro', 'Română'), ('ru', 'русский'), ('sv', 'svenska'), ('tr', 'türk'), ('zh-hant', '中文(台灣)')], default='en', help_text='Prefered language to display pages.', max_length=10, verbose_name='language'),
|
||||
),
|
||||
]
|
||||
@@ -7,7 +7,7 @@ from django.utils.encoding import smart_text
|
||||
|
||||
from modoboa.core.password_hashers.advanced import ( # NOQA:F401
|
||||
BLFCRYPTHasher, MD5CRYPTHasher, SHA256CRYPTHasher, SHA512CRYPTHasher,
|
||||
ARGON2IDHasher
|
||||
ARGON2IDHasher, SSHAHasher
|
||||
)
|
||||
from modoboa.core.password_hashers.base import ( # NOQA:F401
|
||||
CRYPTHasher, MD5Hasher, PLAINHasher, SHA256Hasher
|
||||
|
||||
@@ -4,7 +4,7 @@ Advanced (ie. stronger) password hashers.
|
||||
This module relies on `passlib` to provide more secure hashers.
|
||||
"""
|
||||
|
||||
from passlib.hash import bcrypt, md5_crypt, sha256_crypt, sha512_crypt
|
||||
from passlib.hash import bcrypt, md5_crypt, sha256_crypt, sha512_crypt, ldap_salted_sha1
|
||||
|
||||
try:
|
||||
from argon2 import PasswordHasher as argon2_hasher
|
||||
@@ -113,6 +113,25 @@ class SHA512CRYPTHasher(PasswordHasher):
|
||||
return sha512_crypt.verify(clearvalue, hashed_value)
|
||||
|
||||
|
||||
class SSHAHasher(PasswordHasher):
|
||||
"""
|
||||
Salted SHA1 password hasher.
|
||||
"""
|
||||
_weak = True
|
||||
|
||||
@property
|
||||
def scheme(self):
|
||||
return "{SSHA}"
|
||||
|
||||
def _encrypt(self, clearvalue, salt=None):
|
||||
# We have to remove the {SSHA} at the beginning of the string
|
||||
return ldap_salted_sha1.hash(clearvalue)[6:]
|
||||
|
||||
def verify(self, clearvalue, hashed_value):
|
||||
# We have to add the scheme for the hashed_value to be validated
|
||||
return ldap_salted_sha1.verify(clearvalue, f'{{SSHA}}{hashed_value}')
|
||||
|
||||
|
||||
if argon2_hasher is not None:
|
||||
class ARGON2IDHasher(PasswordHasher):
|
||||
"""
|
||||
|
||||
@@ -110,6 +110,12 @@ class AuthenticationTestCase(ModoTestCase):
|
||||
user.refresh_from_db()
|
||||
self.assertTrue(user.password.startswith("{SHA256}"))
|
||||
|
||||
self.client.logout()
|
||||
self.set_global_parameter("password_scheme", "ssha")
|
||||
self.client.post(reverse("core:login"), data)
|
||||
user.refresh_from_db()
|
||||
self.assertTrue(user.password.startswith("{SSHA}"))
|
||||
|
||||
if argon2 is not None:
|
||||
self.client.logout()
|
||||
self.set_global_parameter("password_scheme", "argon2id")
|
||||
@@ -176,7 +182,7 @@ class AuthenticationTestCase(ModoTestCase):
|
||||
"""Validate Dovecot supported schemes with fake command output."""
|
||||
exec_cmd_mock.return_value = (
|
||||
0,
|
||||
"MD5 MD5-CRYPT SHA SHA1 SHA256 SHA512 SMD5 SSHA SSHA256 SSHA512 "
|
||||
"MD5 MD5-CRYPT SHA SHA1 SSHA SHA256 SHA512 SMD5 SSHA SSHA256 SSHA512 "
|
||||
"PLAIN CLEAR CLEARTEXT PLAIN-TRUNC CRAM-MD5 SCRAM-SHA-1 HMAC-MD5 "
|
||||
"DIGEST-MD5 PLAIN-MD4 PLAIN-MD5 LDAP-MD5 LANMAN NTLM OTP SKEY RPA "
|
||||
"PBKDF2 CRYPT SHA256-CRYPT SHA512-CRYPT"
|
||||
@@ -187,6 +193,7 @@ class AuthenticationTestCase(ModoTestCase):
|
||||
"{MD5-CRYPT}",
|
||||
"{SHA}",
|
||||
"{SHA1}",
|
||||
"{SSHA}",
|
||||
"{SHA256}",
|
||||
"{SHA512}",
|
||||
"{SMD5}",
|
||||
|
||||
@@ -106,7 +106,8 @@ SETTINGS_SAMPLE = {
|
||||
"pdfcredentials-smtp_connection_security": "starttls",
|
||||
"pdfcredentials-imap_server_address": "127.0.0.1",
|
||||
"pdfcredentials-imap_server_port": 667,
|
||||
"pdfcredentials-imap_connection_security": "starttls"
|
||||
"pdfcredentials-imap_connection_security": "starttls",
|
||||
"dmarc-enable_rlookups": False,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"""DMARC related tools for Modoboa."""
|
||||
|
||||
default_app_config = "modoboa.dmarc.apps.DmarcConfig"
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -0,0 +1,32 @@
|
||||
"""App related serializers."""
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class TestResultSerializer(serializers.Serializer):
|
||||
|
||||
success = serializers.IntegerField()
|
||||
failure = serializers.IntegerField()
|
||||
|
||||
|
||||
class SourceSerializer(serializers.Serializer):
|
||||
|
||||
total = serializers.IntegerField()
|
||||
spf = TestResultSerializer()
|
||||
dkim = TestResultSerializer()
|
||||
|
||||
|
||||
class DMARCAligmentSerializer(serializers.Serializer):
|
||||
|
||||
aligned = serializers.DictField(
|
||||
child=serializers.DictField(child=SourceSerializer())
|
||||
)
|
||||
trusted = serializers.DictField(
|
||||
child=serializers.DictField(child=SourceSerializer())
|
||||
)
|
||||
forwarded = serializers.DictField(
|
||||
child=serializers.DictField(child=SourceSerializer())
|
||||
)
|
||||
failed = serializers.DictField(
|
||||
child=serializers.DictField(child=SourceSerializer())
|
||||
)
|
||||
@@ -0,0 +1,36 @@
|
||||
"""API v2 tests."""
|
||||
|
||||
from django.urls import reverse
|
||||
|
||||
from modoboa.lib.tests import ModoAPITestCase
|
||||
|
||||
from modoboa.admin import factories as admin_factories
|
||||
from modoboa.dmarc.tests import mixins
|
||||
|
||||
|
||||
class DmarcViewSetTestCase(mixins.CallCommandMixin, ModoAPITestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create test data."""
|
||||
super().setUpTestData()
|
||||
cls.domain = admin_factories.DomainFactory(name="ngyn.org")
|
||||
|
||||
def test_alignment_stats(self):
|
||||
"""Test alignment stats endpoint."""
|
||||
self.import_reports()
|
||||
url = reverse("v2:dmarc-alignment-stats", args=[self.domain.pk])
|
||||
response = self.client.get(f"{url}?period=2015-26")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(response.json()["failed"]), 1)
|
||||
|
||||
def test_no_record(self):
|
||||
url = reverse("v2:dmarc-alignment-stats", args=[self.domain.pk])
|
||||
response = self.client.get(f"{url}?period=2015-26")
|
||||
self.assertEqual(response.status_code, 204)
|
||||
|
||||
def test_wrong_range(self):
|
||||
self.import_reports()
|
||||
url = reverse("v2:dmarc-alignment-stats", args=[self.domain.pk])
|
||||
response = self.client.get(f"{url}?period=toto-titi")
|
||||
self.assertEqual(response.status_code, 400)
|
||||
@@ -0,0 +1,10 @@
|
||||
"""App related API urls."""
|
||||
|
||||
from rest_framework import routers
|
||||
|
||||
from . import viewsets
|
||||
|
||||
router = routers.SimpleRouter()
|
||||
router.register(r"domains", viewsets.DMARCViewSet, basename="dmarc")
|
||||
|
||||
urlpatterns = router.urls
|
||||
@@ -0,0 +1,38 @@
|
||||
"""App. related viewsets."""
|
||||
|
||||
from rest_framework import permissions, response, viewsets
|
||||
from rest_framework.decorators import action
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.lib.throttle import GetThrottleViewsetMixin
|
||||
|
||||
from ... import lib
|
||||
from . import serializers
|
||||
|
||||
|
||||
class DMARCViewSet(GetThrottleViewsetMixin, viewsets.GenericViewSet):
|
||||
|
||||
permission_classes = (permissions.IsAuthenticated, )
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter queryset based on current user."""
|
||||
return admin_models.Domain.objects.get_for_admin(self.request.user)
|
||||
|
||||
@action(
|
||||
methods=["get"],
|
||||
detail=True,
|
||||
serializer_class=serializers.DMARCAligmentSerializer,
|
||||
url_path="dmarc/alignment_stats"
|
||||
)
|
||||
def alignment_stats(self, request, **kwargs):
|
||||
domain = self.get_object()
|
||||
if not domain.record_set.exists():
|
||||
return response.Response(status=204)
|
||||
try:
|
||||
stats = lib.get_aligment_stats(
|
||||
domain, self.request.query_params.get("period")
|
||||
)
|
||||
except ValueError:
|
||||
return response.Response("Invalid range received", status=400)
|
||||
serializer = self.get_serializer(stats)
|
||||
return response.Response(serializer.data)
|
||||
@@ -0,0 +1,16 @@
|
||||
"""AppConfig for dmarc."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
from modoboa.dmarc.forms import load_settings
|
||||
|
||||
|
||||
class DmarcConfig(AppConfig):
|
||||
"""App configuration."""
|
||||
|
||||
name = "modoboa.dmarc"
|
||||
verbose_name = "Modoboa DMARC tools"
|
||||
|
||||
def ready(self):
|
||||
load_settings()
|
||||
from . import handlers
|
||||
@@ -0,0 +1,10 @@
|
||||
"""DMARC constants."""
|
||||
|
||||
ALLOWED_REASON_TYPES = (
|
||||
"forwarded",
|
||||
"sampled_out",
|
||||
"trusted_forwarder",
|
||||
"mailing_list",
|
||||
"local_policy",
|
||||
"other"
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Custom forms."""
|
||||
|
||||
from django import forms
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from modoboa.lib import form_utils
|
||||
from modoboa.parameters import forms as param_forms
|
||||
|
||||
|
||||
class ReportOptionsForm(forms.Form):
|
||||
"""Report display options."""
|
||||
|
||||
current_year = forms.IntegerField(widget=forms.widgets.HiddenInput)
|
||||
current_week = forms.IntegerField()
|
||||
query = forms.ChoiceField(
|
||||
choices=[("previous", "Previous"), ("next", "Next")])
|
||||
resolve_hostnames = forms.BooleanField(
|
||||
initial=False, required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Constructor."""
|
||||
super().__init__(*args, **kwargs)
|
||||
if not args:
|
||||
year, week, day = timezone.now().isocalendar()
|
||||
self.fields["current_year"].initial = year
|
||||
self.fields["current_week"].initial = week
|
||||
|
||||
|
||||
class ParametersForm(param_forms.AdminParametersForm):
|
||||
"""Extension settings."""
|
||||
|
||||
app = "dmarc"
|
||||
|
||||
qsettings_sep = form_utils.SeparatorField(label=_("DNS settings"))
|
||||
|
||||
enable_rlookups = form_utils.YesNoField(
|
||||
label=_("Enable reverse lookups"),
|
||||
initial=False,
|
||||
help_text=_(
|
||||
"Enable reverse DNS lookups (reports will be longer to display)"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def load_settings():
|
||||
"""Load app settings."""
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", ParametersForm, _("DMARC"))
|
||||
@@ -0,0 +1,22 @@
|
||||
"""Django signal handlers for modoboa_dmarc."""
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.dispatch import receiver
|
||||
|
||||
from modoboa.admin import signals as admin_signals
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_domain_actions)
|
||||
def dmarc_domain_actions(sender, user, domain, **kwargs):
|
||||
"""Return a link to access domain report."""
|
||||
if not models.Record.objects.filter(header_from=domain).exists():
|
||||
return []
|
||||
return [{
|
||||
"name": "dmarc_report",
|
||||
"url": reverse("dmarc:domain_report", args=[domain.pk]),
|
||||
"title": _("Show DMARC report for {}").format(domain.name),
|
||||
"img": "fa fa-pie-chart"
|
||||
}]
|
||||
@@ -0,0 +1,309 @@
|
||||
"""Internal library."""
|
||||
|
||||
import concurrent.futures
|
||||
import datetime
|
||||
import email
|
||||
import fileinput
|
||||
import getpass
|
||||
import imaplib
|
||||
import zipfile
|
||||
import gzip
|
||||
import sys
|
||||
import tldextract
|
||||
|
||||
from defusedxml.ElementTree import fromstring
|
||||
from dns import resolver, reversename
|
||||
import magic
|
||||
import pytz.exceptions
|
||||
import six
|
||||
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from . import constants
|
||||
from . import models
|
||||
|
||||
ZIP_CONTENT_TYPES = [
|
||||
"application/x-zip-compressed",
|
||||
"application/x-zip",
|
||||
"application/zip",
|
||||
"application/gzip",
|
||||
"application/octet-stream",
|
||||
"text/xml",
|
||||
]
|
||||
|
||||
FILE_TYPES = [
|
||||
"text/plain",
|
||||
"text/xml",
|
||||
]
|
||||
|
||||
|
||||
def import_record(xml_node, report):
|
||||
"""Import a record."""
|
||||
record = models.Record(report=report)
|
||||
row = xml_node.find("row")
|
||||
record.source_ip = row.find("source_ip").text
|
||||
record.count = int(row.find("count").text)
|
||||
|
||||
policy_evaluated = row.find("policy_evaluated")
|
||||
record.disposition = policy_evaluated.find("disposition").text
|
||||
record.dkim_result = policy_evaluated.find("dkim").text
|
||||
record.spf_result = policy_evaluated.find("spf").text
|
||||
reason = policy_evaluated.find("reason")
|
||||
if reason:
|
||||
record.reason_type = smart_text(reason.find("type").text)[:14]
|
||||
if record.reason_type not in constants.ALLOWED_REASON_TYPES:
|
||||
record.reason_type = "other"
|
||||
comment = reason.find("comment").text or ""
|
||||
record.reason_comment = comment
|
||||
|
||||
identifiers = xml_node.find("identifiers")
|
||||
header_from = identifiers.find("header_from").text.split(".")
|
||||
domain = None
|
||||
while len(header_from) >= 2:
|
||||
domain = admin_models.Domain.objects.filter(
|
||||
name=".".join(header_from)).first()
|
||||
if domain is not None:
|
||||
record.header_from = domain
|
||||
break
|
||||
header_from = header_from[1:]
|
||||
if domain is None:
|
||||
print("Invalid record found (domain not local)")
|
||||
return None
|
||||
|
||||
record.save()
|
||||
auth_results = xml_node.find("auth_results")
|
||||
for rtype in ["spf", "dkim"]:
|
||||
rnode = auth_results.find(rtype)
|
||||
if not rnode:
|
||||
continue
|
||||
models.Result.objects.create(
|
||||
record=record, type=rtype, domain=rnode.find("domain").text,
|
||||
result=rnode.find("result").text)
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def import_report(content):
|
||||
"""Import an aggregated report."""
|
||||
root = fromstring(content, forbid_dtd=True)
|
||||
metadata = root.find("report_metadata")
|
||||
print(
|
||||
"Importing report {} received from {}".format(
|
||||
metadata.find("report_id").text,
|
||||
metadata.find("org_name").text)
|
||||
)
|
||||
reporter, created = models.Reporter.objects.get_or_create(
|
||||
email=metadata.find("email").text,
|
||||
defaults={"org_name": metadata.find("org_name").text}
|
||||
)
|
||||
qs = models.Report.objects.filter(
|
||||
reporter=reporter, report_id=metadata.find("report_id").text)
|
||||
if qs.exists():
|
||||
print("Report already imported.")
|
||||
return
|
||||
report = models.Report(reporter=reporter)
|
||||
|
||||
report.report_id = metadata.find("report_id").text
|
||||
date_range = metadata.find("date_range")
|
||||
report.start_date = timezone.make_aware(
|
||||
datetime.datetime.fromtimestamp(int(date_range.find("begin").text))
|
||||
)
|
||||
report.end_date = timezone.make_aware(
|
||||
datetime.datetime.fromtimestamp(int(date_range.find("end").text))
|
||||
)
|
||||
|
||||
policy_published = root.find("policy_published")
|
||||
for attr in ["domain", "adkim", "aspf", "p", "sp", "pct"]:
|
||||
node = policy_published.find(attr)
|
||||
if node is None or not node.text:
|
||||
if attr == "sp":
|
||||
node = fromstring('<sp>unstated</sp>', forbid_dtd=True)
|
||||
else:
|
||||
print(f"Report skipped because of malformed data (empty {attr})")
|
||||
return
|
||||
value = setattr(report, "policy_{}".format(attr), node.text)
|
||||
try:
|
||||
report.save()
|
||||
except (pytz.exceptions.AmbiguousTimeError):
|
||||
print("Report skipped because of invalid date.")
|
||||
return
|
||||
for record in root.findall("record"):
|
||||
import_record(record, report)
|
||||
|
||||
|
||||
def import_archive(archive, content_type=None):
|
||||
"""Import reports contained inside (file pointer)
|
||||
- a zip archive,
|
||||
- a gzip file,
|
||||
- a xml file.
|
||||
"""
|
||||
if content_type == "text/xml":
|
||||
import_report(archive.read())
|
||||
elif content_type in ["application/gzip", "application/octet-stream"]:
|
||||
with gzip.GzipFile(mode="r", fileobj=archive) as zfile:
|
||||
import_report(zfile.read())
|
||||
else:
|
||||
with zipfile.ZipFile(archive, "r") as zfile:
|
||||
for fname in zfile.namelist():
|
||||
import_report(zfile.read(fname))
|
||||
|
||||
|
||||
def import_report_from_email(content):
|
||||
"""Import a report from an email."""
|
||||
if isinstance(content, six.string_types):
|
||||
msg = email.message_from_string(content)
|
||||
elif isinstance(content, six.binary_type):
|
||||
msg = email.message_from_bytes(content)
|
||||
else:
|
||||
msg = email.message_from_file(content)
|
||||
err = False
|
||||
for part in msg.walk():
|
||||
if part.get_content_type() not in ZIP_CONTENT_TYPES:
|
||||
continue
|
||||
try:
|
||||
fpo = six.BytesIO(part.get_payload(decode=True))
|
||||
# Try to get the actual file type of the buffer
|
||||
# required to make sure we are dealing with an XML file
|
||||
file_type = magic.Magic(uncompress=True, mime=True).from_buffer(fpo.read(2048))
|
||||
fpo.seek(0)
|
||||
if file_type in FILE_TYPES:
|
||||
import_archive(fpo, content_type=part.get_content_type())
|
||||
except (OSError, IOError):
|
||||
print('Error: the attachment does not match the mimetype')
|
||||
err = True
|
||||
else:
|
||||
fpo.close()
|
||||
if err:
|
||||
# Return EX_DATAERR code <data format error> available
|
||||
# at sysexits.h file
|
||||
# (see http://www.postfix.org/pipe.8.html)
|
||||
sys.exit(65)
|
||||
|
||||
|
||||
def import_report_from_stdin():
|
||||
"""Parse a report from stdin."""
|
||||
content = six.StringIO()
|
||||
for line in fileinput.input([]):
|
||||
content.write(line)
|
||||
content.seek(0)
|
||||
|
||||
if not content:
|
||||
return
|
||||
import_report_from_email(content)
|
||||
|
||||
|
||||
def import_from_imap(options):
|
||||
"""Import reports from an IMAP mailbox."""
|
||||
obj = imaplib.IMAP4_SSL if options["ssl"] else imaplib.IMAP4
|
||||
conn = obj(options["host"])
|
||||
username = input("Username: ")
|
||||
password = getpass.getpass(prompt="Password: ")
|
||||
conn.login(username, password)
|
||||
conn.select(options["mailbox"])
|
||||
type, msg_ids = conn.search(None, "ALL")
|
||||
for msg_id in msg_ids[0].split():
|
||||
typ, content = conn.fetch(msg_id, "(RFC822)")
|
||||
for response_part in content:
|
||||
if isinstance(response_part, tuple):
|
||||
import_report_from_email(response_part[1])
|
||||
conn.close()
|
||||
|
||||
|
||||
def week_range(year, weeknumber):
|
||||
"""Return start and end dates of a given week."""
|
||||
tz = timezone.get_current_timezone()
|
||||
fmt = "%Y-%W-%w"
|
||||
start_week = datetime.datetime.strptime(
|
||||
"{}-{}-{}".format(year, weeknumber, 1), fmt)
|
||||
end_week = datetime.datetime.strptime(
|
||||
"{}-{}-{}".format(year, weeknumber, 0), fmt)
|
||||
return tz.localize(start_week), tz.localize(end_week)
|
||||
|
||||
|
||||
def insert_record(target: dict, record, name: str) -> None:
|
||||
"""Add a record."""
|
||||
if name not in target:
|
||||
target[name] = {}
|
||||
|
||||
if record.source_ip not in target[name]:
|
||||
target[name][record.source_ip] = {
|
||||
"total": 0,
|
||||
"spf": {"success": 0, "failure": 0},
|
||||
"dkim": {"success": 0, "failure": 0}
|
||||
}
|
||||
target[name][record.source_ip]["total"] += record.count
|
||||
for typ in ["spf", "dkim"]:
|
||||
result = getattr(record, "{}_result".format(typ))
|
||||
key = "success" if result == "pass" else "failure"
|
||||
target[name][record.source_ip][typ][key] += record.count
|
||||
|
||||
|
||||
def get_aligment_stats(domain, period=None) -> dict:
|
||||
"""Retrieve aligment statistics for given domain."""
|
||||
if not period:
|
||||
year, week, day = timezone.now().isocalendar()
|
||||
week -= 1
|
||||
period = f"{year}-{week}"
|
||||
else:
|
||||
year, week = period.split("-")
|
||||
if not year or not week:
|
||||
period = f"{year}-{week}"
|
||||
|
||||
daterange = week_range(year, week)
|
||||
qargs = (
|
||||
(Q(report__start_date__gte=daterange[0],
|
||||
report__start_date__lte=daterange[1]) |
|
||||
Q(report__end_date__gte=daterange[0],
|
||||
report__end_date__lte=daterange[1])) &
|
||||
Q(header_from=domain)
|
||||
)
|
||||
all_records = models.Record.objects.filter(qargs)
|
||||
stats: dict = {
|
||||
"aligned": {},
|
||||
"trusted": {},
|
||||
"forwarded": {},
|
||||
"failed": {}
|
||||
}
|
||||
|
||||
dns_names = {}
|
||||
if param_tools.get_global_parameter("enable_rlookups"):
|
||||
dns_resolver = resolver.Resolver()
|
||||
dns_resolver.timeout = 1.0
|
||||
dns_resolver.lifetime = 1.0
|
||||
|
||||
def get_domain_name_from_ip(ip):
|
||||
addr = reversename.from_address(ip)
|
||||
try:
|
||||
resp = dns_resolver.query(addr, "PTR")
|
||||
ext = tldextract.extract(str(resp[0].target))
|
||||
if not ext.suffix: # invalid PTR record
|
||||
raise resolver.NXDOMAIN()
|
||||
return (ip, '.'.join((ext.domain, ext.suffix)).lower())
|
||||
except (resolver.NXDOMAIN, resolver.YXDOMAIN,
|
||||
resolver.NoAnswer, resolver.NoNameservers,
|
||||
resolver.Timeout):
|
||||
return (None, None)
|
||||
|
||||
ips = (r.source_ip for r in all_records)
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=16) as pool:
|
||||
dns_names = {i: n for (i, n) in
|
||||
list(pool.map(get_domain_name_from_ip, ips))}
|
||||
|
||||
for record in all_records:
|
||||
name = dns_names.get(record.source_ip, _("Not resolved"))
|
||||
if record.dkim_result == "pass" and record.spf_result == "pass":
|
||||
insert_record(stats["aligned"], record, name)
|
||||
elif record.dkim_result == "pass" or record.spf_result == "pass":
|
||||
insert_record(stats["trusted"], record, name)
|
||||
elif record.reason_type == "local_policy" and record.reason_comment.startswith("arc=pass"):
|
||||
insert_record(stats["forwarded"], record, name)
|
||||
else:
|
||||
insert_record(stats["failed"], record, name)
|
||||
|
||||
return stats
|
||||
@@ -0,0 +1,138 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Irriep Nala Novram <allannkorh@yahoo.fr>, 2019
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-05-06 14:05+0200\n"
|
||||
"PO-Revision-Date: 2020-05-06 12:07+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Breton (http://www.transifex.com/tonio/modoboa/language/br/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: br\n"
|
||||
"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);\n"
|
||||
|
||||
#: forms.py:35
|
||||
msgid "DNS settings"
|
||||
msgstr "Arventennoù DNS"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Enable reverse lookups"
|
||||
msgstr "Enaouiñ an enklaskoù eilpennet"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Enable reverse DNS lookups (reports will be longer to display)"
|
||||
msgstr "Enaouiñ an enklaskoù DNS eilpennet (danevelloù a vo hiroc'h da vezañ diskouezet)"
|
||||
|
||||
#: handlers.py:20
|
||||
msgid "Show DMARC report for {}"
|
||||
msgstr "Diskouez an danevell DMARC evit {}"
|
||||
|
||||
#: models.py:10 models.py:16
|
||||
msgid "None"
|
||||
msgstr "Hini ebet"
|
||||
|
||||
#: models.py:11
|
||||
msgid "Quarantine"
|
||||
msgstr "Dispell"
|
||||
|
||||
#: models.py:12
|
||||
msgid "Reject"
|
||||
msgstr "Nac'hañ"
|
||||
|
||||
#: models.py:17
|
||||
msgid "Neutral"
|
||||
msgstr "Neptu"
|
||||
|
||||
#: models.py:18
|
||||
msgid "Pass"
|
||||
msgstr "Tremen"
|
||||
|
||||
#: models.py:19
|
||||
msgid "Fail"
|
||||
msgstr "Sac'hadenn"
|
||||
|
||||
#: models.py:20
|
||||
msgid "Temporary error"
|
||||
msgstr "Fazi padennek"
|
||||
|
||||
#: models.py:21
|
||||
msgid "Permanent error"
|
||||
msgstr "Fazi peurbadus"
|
||||
|
||||
#: models.py:25
|
||||
msgid "Policy"
|
||||
msgstr "Politikerezh"
|
||||
|
||||
#: models.py:29
|
||||
msgid "Soft failure"
|
||||
msgstr "Sac'hadenn wan"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "DMARC tools"
|
||||
msgstr "Ostilhoù DMARC"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "A set of tools to ease DMARC integration"
|
||||
msgstr "Un dastumad ostilhoù da aesaat enframmañ DMARC"
|
||||
|
||||
#: templates/modoboa_dmarc/_result_detail.html:6
|
||||
msgid "Total"
|
||||
msgstr "Hollad"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:21
|
||||
#: templates/modoboa_dmarc/domain_report.html:26
|
||||
msgid "Fully aligned"
|
||||
msgstr "Linennet penn-da-benn"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:22
|
||||
#: templates/modoboa_dmarc/domain_report.html:27
|
||||
msgid "Partially aligned"
|
||||
msgstr "Linennet dre an hanter"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:23
|
||||
#: templates/modoboa_dmarc/domain_report.html:28
|
||||
msgid "Failed"
|
||||
msgstr "C'hwitet"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:50
|
||||
msgid "DMARC report for"
|
||||
msgstr "Danevell DMARC evit"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:74
|
||||
msgid "processed"
|
||||
msgstr "tretet"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:83
|
||||
msgid "fully aligned"
|
||||
msgstr "linennet penn-da-benn"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:92
|
||||
msgid "partially aligned"
|
||||
msgstr "linennet dre an hanter"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:101
|
||||
msgid "failed"
|
||||
msgstr "c'hwitet"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:111
|
||||
msgid "Display details"
|
||||
msgstr "Diskouez ar munudoù"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:115
|
||||
msgid "Trusted sources"
|
||||
msgstr "Mammennoù fizius"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:123
|
||||
msgid "Unknown sources / Threats"
|
||||
msgstr "Mammennoù dizanv/Gourdrouzioù"
|
||||
|
||||
#: templatetags/dmarc_tags.py:59 views.py:120
|
||||
msgid "Not resolved"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,139 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Jan Laufik, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-05-06 14:05+0200\n"
|
||||
"PO-Revision-Date: 2017-03-03 08:18+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/tonio/"
|
||||
"modoboa/language/cs_CZ/)\n"
|
||||
"Language: cs_CZ\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: forms.py:35
|
||||
msgid "DNS settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Enable reverse lookups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Enable reverse DNS lookups (reports will be longer to display)"
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:20
|
||||
msgid "Show DMARC report for {}"
|
||||
msgstr "Zobrazit DMARC zprávu pro {}"
|
||||
|
||||
#: models.py:10 models.py:16
|
||||
msgid "None"
|
||||
msgstr "Nic"
|
||||
|
||||
#: models.py:11
|
||||
msgid "Quarantine"
|
||||
msgstr "Karanténa"
|
||||
|
||||
#: models.py:12
|
||||
msgid "Reject"
|
||||
msgstr "Odmítnout"
|
||||
|
||||
#: models.py:17
|
||||
msgid "Neutral"
|
||||
msgstr "Neutrální"
|
||||
|
||||
#: models.py:18
|
||||
msgid "Pass"
|
||||
msgstr "Úspěch"
|
||||
|
||||
#: models.py:19
|
||||
msgid "Fail"
|
||||
msgstr "Selhání"
|
||||
|
||||
#: models.py:20
|
||||
msgid "Temporary error"
|
||||
msgstr "Dočasná chyba"
|
||||
|
||||
#: models.py:21
|
||||
msgid "Permanent error"
|
||||
msgstr "Permanentní chyba"
|
||||
|
||||
#: models.py:25
|
||||
msgid "Policy"
|
||||
msgstr "Politika"
|
||||
|
||||
#: models.py:29
|
||||
msgid "Soft failure"
|
||||
msgstr "Selhání bez odmítnutí"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "DMARC tools"
|
||||
msgstr "DMARC nástroje"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "A set of tools to ease DMARC integration"
|
||||
msgstr "Sada nástrojů pro zjednodušení integrace DMARC"
|
||||
|
||||
#: templates/modoboa_dmarc/_result_detail.html:6
|
||||
msgid "Total"
|
||||
msgstr "Celkem"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:21
|
||||
#: templates/modoboa_dmarc/domain_report.html:26
|
||||
msgid "Fully aligned"
|
||||
msgstr "Plně v souladu"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:22
|
||||
#: templates/modoboa_dmarc/domain_report.html:27
|
||||
msgid "Partially aligned"
|
||||
msgstr "Částečně v souladu"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:23
|
||||
#: templates/modoboa_dmarc/domain_report.html:28
|
||||
msgid "Failed"
|
||||
msgstr "Selhalo"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:50
|
||||
msgid "DMARC report for"
|
||||
msgstr "DMARC zpráva pro"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:74
|
||||
msgid "processed"
|
||||
msgstr "zpracované"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:83
|
||||
msgid "fully aligned"
|
||||
msgstr "plně v souladu"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:92
|
||||
msgid "partially aligned"
|
||||
msgstr "částečně v souladu"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:101
|
||||
msgid "failed"
|
||||
msgstr "selhalo"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:111
|
||||
msgid "Display details"
|
||||
msgstr "Zobrazit podrobnosti"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:115
|
||||
msgid "Trusted sources"
|
||||
msgstr "Důvěryhodné zdroje"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:123
|
||||
msgid "Unknown sources / Threats"
|
||||
msgstr "Neznáme zdroje / Hrozby"
|
||||
|
||||
#: templatetags/dmarc_tags.py:59 views.py:120
|
||||
msgid "Not resolved"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,139 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# controlc.de, 2015
|
||||
# Tobias Strobel, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-05-06 14:05+0200\n"
|
||||
"PO-Revision-Date: 2017-03-03 08:18+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: German (http://www.transifex.com/tonio/modoboa/language/de/)\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:35
|
||||
msgid "DNS settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Enable reverse lookups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Enable reverse DNS lookups (reports will be longer to display)"
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:20
|
||||
msgid "Show DMARC report for {}"
|
||||
msgstr "DMARC-Bericht für {} anzeigen"
|
||||
|
||||
#: models.py:10 models.py:16
|
||||
msgid "None"
|
||||
msgstr "Nichts"
|
||||
|
||||
#: models.py:11
|
||||
msgid "Quarantine"
|
||||
msgstr "Quarantäne"
|
||||
|
||||
#: models.py:12
|
||||
msgid "Reject"
|
||||
msgstr "Ablehnung"
|
||||
|
||||
#: models.py:17
|
||||
msgid "Neutral"
|
||||
msgstr "Neutral"
|
||||
|
||||
#: models.py:18
|
||||
msgid "Pass"
|
||||
msgstr "Genehmigen"
|
||||
|
||||
#: models.py:19
|
||||
msgid "Fail"
|
||||
msgstr "Abbruch"
|
||||
|
||||
#: models.py:20
|
||||
msgid "Temporary error"
|
||||
msgstr "Temporärer Fehler"
|
||||
|
||||
#: models.py:21
|
||||
msgid "Permanent error"
|
||||
msgstr "Permanenter Fehler"
|
||||
|
||||
#: models.py:25
|
||||
msgid "Policy"
|
||||
msgstr "Richtlinie"
|
||||
|
||||
#: models.py:29
|
||||
msgid "Soft failure"
|
||||
msgstr "Schwacher Fehler"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "DMARC tools"
|
||||
msgstr "DMARC-Tools"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "A set of tools to ease DMARC integration"
|
||||
msgstr "Ein Set von Tools um die DMARC-Integration zu vereinfachen"
|
||||
|
||||
#: templates/modoboa_dmarc/_result_detail.html:6
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:21
|
||||
#: templates/modoboa_dmarc/domain_report.html:26
|
||||
msgid "Fully aligned"
|
||||
msgstr "Voll zugeordnet"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:22
|
||||
#: templates/modoboa_dmarc/domain_report.html:27
|
||||
msgid "Partially aligned"
|
||||
msgstr "Teilweise zugeordnet"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:23
|
||||
#: templates/modoboa_dmarc/domain_report.html:28
|
||||
msgid "Failed"
|
||||
msgstr "Fehlgeschlagen"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:50
|
||||
msgid "DMARC report for"
|
||||
msgstr "DMARC-Bericht für"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:74
|
||||
msgid "processed"
|
||||
msgstr "durchgeführt"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:83
|
||||
msgid "fully aligned"
|
||||
msgstr "voll zugeordnet"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:92
|
||||
msgid "partially aligned"
|
||||
msgstr "teilweise zugeordnet"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:101
|
||||
msgid "failed"
|
||||
msgstr "fehlgeschlagen"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:111
|
||||
msgid "Display details"
|
||||
msgstr "Anzeigedetails"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:115
|
||||
msgid "Trusted sources"
|
||||
msgstr "Vertraute Quellen"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:123
|
||||
msgid "Unknown sources / Threats"
|
||||
msgstr "Unbekannte Quellen / Bedrohungen"
|
||||
|
||||
#: templatetags/dmarc_tags.py:59 views.py:120
|
||||
msgid "Not resolved"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,140 @@
|
||||
# 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: 2020-05-06 14:05+0200\n"
|
||||
"PO-Revision-Date: 2017-10-12 09:55+0000\n"
|
||||
"Last-Translator: Kostas Moumouris <moumouriskostas@gmail.com>\n"
|
||||
"Language-Team: Greek (Greece) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/el_GR/)\n"
|
||||
"Language: el_GR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:35
|
||||
msgid "DNS settings"
|
||||
msgstr "Ρυθμίσεις DNS"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Enable reverse lookups"
|
||||
msgstr "Ενεργοποίηση ανάστροφης αναζήτησης reverse lookups"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Enable reverse DNS lookups (reports will be longer to display)"
|
||||
msgstr "Ενεργοποίηση reverse DNS lookups (η αναφορές θα καθυστερούν)"
|
||||
|
||||
#: handlers.py:20
|
||||
msgid "Show DMARC report for {}"
|
||||
msgstr "Εμφάνιση της έκθεσης DMARC του {}"
|
||||
|
||||
#: models.py:10 models.py:16
|
||||
msgid "None"
|
||||
msgstr "Κανένα"
|
||||
|
||||
#: models.py:11
|
||||
msgid "Quarantine"
|
||||
msgstr "Καραντίνα"
|
||||
|
||||
#: models.py:12
|
||||
msgid "Reject"
|
||||
msgstr "Απόρριψη"
|
||||
|
||||
#: models.py:17
|
||||
msgid "Neutral"
|
||||
msgstr "Ουδέτερο"
|
||||
|
||||
#: models.py:18
|
||||
msgid "Pass"
|
||||
msgstr "Εγκρίθηκε"
|
||||
|
||||
#: models.py:19
|
||||
msgid "Fail"
|
||||
msgstr "Απορρίφθηκε"
|
||||
|
||||
#: models.py:20
|
||||
msgid "Temporary error"
|
||||
msgstr "προσωρινό σφάλμα"
|
||||
|
||||
#: models.py:21
|
||||
msgid "Permanent error"
|
||||
msgstr "Μόνιμο σφάλμα"
|
||||
|
||||
#: models.py:25
|
||||
msgid "Policy"
|
||||
msgstr "Πολιτική"
|
||||
|
||||
#: models.py:29
|
||||
msgid "Soft failure"
|
||||
msgstr "Πρόβλημα Soft"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "DMARC tools"
|
||||
msgstr "Εργαλεία DMARC"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "A set of tools to ease DMARC integration"
|
||||
msgstr "Ένα σετ εργαλείων για την απλοποίηση της ενσωμάτωσης του DMARC"
|
||||
|
||||
#: templates/modoboa_dmarc/_result_detail.html:6
|
||||
msgid "Total"
|
||||
msgstr "Σύνολο"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:21
|
||||
#: templates/modoboa_dmarc/domain_report.html:26
|
||||
msgid "Fully aligned"
|
||||
msgstr "Πλήρως ευθυγραμμισμένο"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:22
|
||||
#: templates/modoboa_dmarc/domain_report.html:27
|
||||
msgid "Partially aligned"
|
||||
msgstr "Μερικός ευθυγραμισμένα"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:23
|
||||
#: templates/modoboa_dmarc/domain_report.html:28
|
||||
msgid "Failed"
|
||||
msgstr "Απέτυχε"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:50
|
||||
msgid "DMARC report for"
|
||||
msgstr "Έκθεση DMARC του"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:74
|
||||
msgid "processed"
|
||||
msgstr "Επεξεργάστηκε"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:83
|
||||
msgid "fully aligned"
|
||||
msgstr "πλήρως ευθυγραμμισμένο"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:92
|
||||
msgid "partially aligned"
|
||||
msgstr "Μερικώς ευθυγραμμισμένο"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:101
|
||||
msgid "failed"
|
||||
msgstr "απέτυχε"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:111
|
||||
msgid "Display details"
|
||||
msgstr "Προβολή λεπτομερειών"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:115
|
||||
msgid "Trusted sources"
|
||||
msgstr "Αξιόπιστες πηγές"
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:123
|
||||
msgid "Unknown sources / Threats"
|
||||
msgstr "Άγνωστες πηγές / Απειλές"
|
||||
|
||||
#: templatetags/dmarc_tags.py:59 views.py:120
|
||||
msgid "Not resolved"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,137 @@
|
||||
# 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: 2020-05-06 14:05+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"
|
||||
|
||||
#: forms.py:35
|
||||
msgid "DNS settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Enable reverse lookups"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Enable reverse DNS lookups (reports will be longer to display)"
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:20
|
||||
msgid "Show DMARC report for {}"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:10 models.py:16
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:11
|
||||
msgid "Quarantine"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:12
|
||||
msgid "Reject"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:17
|
||||
msgid "Neutral"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:18
|
||||
msgid "Pass"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:19
|
||||
msgid "Fail"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:20
|
||||
msgid "Temporary error"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:21
|
||||
msgid "Permanent error"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:25
|
||||
msgid "Policy"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:29
|
||||
msgid "Soft failure"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "DMARC tools"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "A set of tools to ease DMARC integration"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/_result_detail.html:6
|
||||
msgid "Total"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:21
|
||||
#: templates/modoboa_dmarc/domain_report.html:26
|
||||
msgid "Fully aligned"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:22
|
||||
#: templates/modoboa_dmarc/domain_report.html:27
|
||||
msgid "Partially aligned"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:23
|
||||
#: templates/modoboa_dmarc/domain_report.html:28
|
||||
msgid "Failed"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:50
|
||||
msgid "DMARC report for"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:74
|
||||
msgid "processed"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:83
|
||||
msgid "fully aligned"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:92
|
||||
msgid "partially aligned"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:101
|
||||
msgid "failed"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:111
|
||||
msgid "Display details"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:115
|
||||
msgid "Trusted sources"
|
||||
msgstr ""
|
||||
|
||||
#: templates/modoboa_dmarc/domain_report.html:123
|
||||
msgid "Unknown sources / Threats"
|
||||
msgstr ""
|
||||
|
||||
#: templatetags/dmarc_tags.py:59 views.py:120
|
||||
msgid "Not resolved"
|
||||
msgstr ""
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user