mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge branch 'dev' into bullseye
This commit is contained in:
commit
70bff61749
58 changed files with 2536 additions and 440 deletions
|
@ -53,15 +53,17 @@ full-tests:
|
|||
test-i18n-keys:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest tests tests/test_i18n_keys.py
|
||||
- python3 -m pytest tests/test_i18n_keys.py
|
||||
only:
|
||||
changes:
|
||||
- locales/*
|
||||
- locales/en.json
|
||||
- src/yunohost/*.py
|
||||
- data/hooks/diagnosis/*.py
|
||||
|
||||
test-translation-format-consistency:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python3 -m pytest tests tests/test_translation_format_consistency.py
|
||||
- python3 -m pytest tests/test_translation_format_consistency.py
|
||||
only:
|
||||
changes:
|
||||
- locales/*
|
||||
|
@ -181,3 +183,12 @@ test-service:
|
|||
only:
|
||||
changes:
|
||||
- src/yunohost/service.py
|
||||
|
||||
test-ldapauth:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python3 -m pytest tests/test_ldapauth.py
|
||||
only:
|
||||
changes:
|
||||
- src/yunohost/authenticators/*.py
|
||||
|
|
|
@ -16,7 +16,7 @@ remove-stale-translated-strings:
|
|||
# create a local branch that will overwrite distant one
|
||||
- git checkout -b "ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}" --no-track
|
||||
- python3 remove_stale_translated_strings.py
|
||||
- '[ $(git diff | wc -l) != 0 ] || exit 0' # stop if there is nothing to commit
|
||||
- '[ $(git diff -w | wc -l) != 0 ] || exit 0' # stop if there is nothing to commit
|
||||
- git commit -am "[CI] Remove stale translated strings" || true
|
||||
- git push -f origin "ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}":"ci-remove-stale-translated-strings-${CI_COMMIT_REF_NAME}"
|
||||
- hub pull-request -m "[CI] Remove stale translated strings" -b Yunohost:dev -p || true # GITHUB_USER and GITHUB_TOKEN registered here https://gitlab.com/yunohost/yunohost/-/settings/ci_cd
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
<div align="center">
|
||||
|
||||
[](https://travis-ci.org/YunoHost/yunohost)
|
||||
[](https://github.com/YunoHost/yunohost/blob/stretch-unstable/LICENSE)
|
||||
[](https://gitlab.com/yunohost/yunohost/-/pipelines)
|
||||
[](https://github.com/YunoHost/yunohost/blob/dev/LICENSE)
|
||||
[](https://mastodon.social/@yunohost)
|
||||
|
||||
</div>
|
||||
|
@ -35,7 +35,7 @@ Webadmin ([Yunohost-Admin](https://github.com/YunoHost/yunohost-admin)) | Single
|
|||
- You can help translate YunoHost on our [translation platform](https://translate.yunohost.org/engage/yunohost/?utm_source=widget)
|
||||
|
||||
<p align="center">
|
||||
<img src="https://translate.yunohost.org/widgets/yunohost/-/multi-auto.svg" alt="Translation status" />
|
||||
<img src="https://translate.yunohost.org/widgets/yunohost/-/core/horizontal-auto.svg" alt="Translation status" />
|
||||
</p>
|
||||
|
||||
## License
|
||||
|
|
173
bin/yunomdns
Executable file
173
bin/yunomdns
Executable file
|
@ -0,0 +1,173 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Pythonic declaration of mDNS .local domains for YunoHost
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
import socket
|
||||
from time import sleep
|
||||
from typing import List, Dict
|
||||
|
||||
from zeroconf import Zeroconf, ServiceInfo
|
||||
|
||||
# Helper command taken from Moulinette
|
||||
def check_output(args, stderr=subprocess.STDOUT, shell=True, **kwargs):
|
||||
"""Run command with arguments and return its output as a byte string
|
||||
Overwrite some of the arguments to capture standard error in the result
|
||||
and use shell by default before calling subprocess.check_output.
|
||||
"""
|
||||
return (
|
||||
subprocess.check_output(args, stderr=stderr, shell=shell, **kwargs)
|
||||
.decode("utf-8")
|
||||
.strip()
|
||||
)
|
||||
|
||||
# Helper command taken from Moulinette
|
||||
def _extract_inet(string, skip_netmask=False, skip_loopback=True):
|
||||
"""
|
||||
Extract IP addresses (v4 and/or v6) from a string limited to one
|
||||
address by protocol
|
||||
|
||||
Keyword argument:
|
||||
string -- String to search in
|
||||
skip_netmask -- True to skip subnet mask extraction
|
||||
skip_loopback -- False to include addresses reserved for the
|
||||
loopback interface
|
||||
|
||||
Returns:
|
||||
A dict of {protocol: address} with protocol one of 'ipv4' or 'ipv6'
|
||||
|
||||
"""
|
||||
ip4_pattern = (
|
||||
r"((25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}"
|
||||
)
|
||||
ip6_pattern = r"(((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::?((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)"
|
||||
ip4_pattern += r"/[0-9]{1,2})" if not skip_netmask else ")"
|
||||
ip6_pattern += r"/[0-9]{1,3})" if not skip_netmask else ")"
|
||||
result = {}
|
||||
|
||||
for m in re.finditer(ip4_pattern, string):
|
||||
addr = m.group(1)
|
||||
if skip_loopback and addr.startswith("127."):
|
||||
continue
|
||||
|
||||
# Limit to only one result
|
||||
result["ipv4"] = addr
|
||||
break
|
||||
|
||||
for m in re.finditer(ip6_pattern, string):
|
||||
addr = m.group(1)
|
||||
if skip_loopback and addr == "::1":
|
||||
continue
|
||||
|
||||
# Limit to only one result
|
||||
result["ipv6"] = addr
|
||||
break
|
||||
|
||||
return result
|
||||
|
||||
# Helper command taken from Moulinette
|
||||
def get_network_interfaces():
|
||||
|
||||
# Get network devices and their addresses (raw infos from 'ip addr')
|
||||
devices_raw = {}
|
||||
output = check_output("ip --brief a").split("\n")
|
||||
for line in output:
|
||||
line = line.split()
|
||||
iname = line[0]
|
||||
ips = ' '.join(line[2:])
|
||||
|
||||
devices_raw[iname] = ips
|
||||
|
||||
# Parse relevant informations for each of them
|
||||
devices = {
|
||||
name: _extract_inet(addrs)
|
||||
for name, addrs in devices_raw.items()
|
||||
if name != "lo"
|
||||
}
|
||||
|
||||
return devices
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
###
|
||||
# CONFIG
|
||||
###
|
||||
|
||||
with open('/etc/yunohost/mdns.yml', 'r') as f:
|
||||
config = yaml.safe_load(f) or {}
|
||||
updated = False
|
||||
|
||||
required_fields = ["interfaces", "domains"]
|
||||
missing_fields = [field for field in required_fields if field not in config]
|
||||
|
||||
if missing_fields:
|
||||
print("The fields %s are required" % ', '.join(missing_fields))
|
||||
|
||||
if config['interfaces'] is None:
|
||||
print('No interface listed for broadcast.')
|
||||
sys.exit(0)
|
||||
|
||||
if 'yunohost.local' not in config['domains']:
|
||||
config['domains'].append('yunohost.local')
|
||||
|
||||
zcs = {}
|
||||
interfaces = get_network_interfaces()
|
||||
for interface in config['interfaces']:
|
||||
infos = [] # List of ServiceInfo objects, to feed Zeroconf
|
||||
ips = [] # Human-readable IPs
|
||||
b_ips = [] # Binary-convered IPs
|
||||
|
||||
ipv4 = interfaces[interface]['ipv4'].split('/')[0]
|
||||
if ipv4:
|
||||
ips.append(ipv4)
|
||||
b_ips.append(socket.inet_pton(socket.AF_INET, ipv4))
|
||||
|
||||
ipv6 = interfaces[interface]['ipv6'].split('/')[0]
|
||||
if ipv6:
|
||||
ips.append(ipv6)
|
||||
b_ips.append(socket.inet_pton(socket.AF_INET6, ipv6))
|
||||
|
||||
# If at least one IP is listed
|
||||
if ips:
|
||||
# Create a Zeroconf object, and store the ServiceInfos
|
||||
zc = Zeroconf(interfaces=ips)
|
||||
zcs[zc]=[]
|
||||
for d in config['domains']:
|
||||
d_domain=d.replace('.local','')
|
||||
if '.' in d_domain:
|
||||
print(d_domain+'.local: subdomains are not supported.')
|
||||
else:
|
||||
# Create a ServiceInfo object for each .local domain
|
||||
zcs[zc].append(ServiceInfo(
|
||||
type_='_device-info._tcp.local.',
|
||||
name=interface+': '+d_domain+'._device-info._tcp.local.',
|
||||
addresses=b_ips,
|
||||
port=80,
|
||||
server=d+'.',
|
||||
))
|
||||
print('Adding '+d+' with addresses '+str(ips)+' on interface '+interface)
|
||||
|
||||
# Run registration
|
||||
print("Registering...")
|
||||
for zc, infos in zcs.items():
|
||||
for info in infos:
|
||||
zc.register_service(info)
|
||||
|
||||
try:
|
||||
print("Registered. Press Ctrl+C or stop service to stop.")
|
||||
while True:
|
||||
sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
print("Unregistering...")
|
||||
for zc, infos in zcs.items():
|
||||
for info in infos:
|
||||
zc.unregister_service(info)
|
||||
zc.close()
|
|
@ -33,18 +33,10 @@
|
|||
# Global parameters #
|
||||
#############################
|
||||
_global:
|
||||
configuration:
|
||||
authenticate:
|
||||
- api
|
||||
authenticator:
|
||||
default:
|
||||
vendor: ldap
|
||||
help: admin_password
|
||||
parameters:
|
||||
uri: ldap://localhost:389
|
||||
base_dn: dc=yunohost,dc=org
|
||||
user_rdn: cn=admin,dc=yunohost,dc=org
|
||||
argument_auth: false
|
||||
name: yunohost.admin
|
||||
authentication:
|
||||
api: ldap_admin
|
||||
cli: null
|
||||
arguments:
|
||||
-v:
|
||||
full: --version
|
||||
|
@ -661,7 +653,11 @@ app:
|
|||
api: DELETE /apps/<app>
|
||||
arguments:
|
||||
app:
|
||||
help: App to delete
|
||||
help: App to remove
|
||||
-p:
|
||||
full: --purge
|
||||
help: Also remove all application data
|
||||
action: store_true
|
||||
|
||||
### app_upgrade()
|
||||
upgrade:
|
||||
|
@ -681,6 +677,10 @@ app:
|
|||
full: --force
|
||||
help: Force the update, even though the app is up to date
|
||||
action: store_true
|
||||
-b:
|
||||
full: --no-safety-backup
|
||||
help: Disable the safety backup during upgrade
|
||||
action: store_true
|
||||
|
||||
### app_change_url()
|
||||
change-url:
|
||||
|
@ -1305,9 +1305,9 @@ tools:
|
|||
postinstall:
|
||||
action_help: YunoHost post-install
|
||||
api: POST /postinstall
|
||||
configuration:
|
||||
authentication:
|
||||
# We need to be able to run the postinstall without being authenticated, otherwise we can't run the postinstall
|
||||
authenticate: false
|
||||
api: null
|
||||
arguments:
|
||||
-d:
|
||||
full: --domain
|
||||
|
|
|
@ -31,7 +31,11 @@ ynh_multimedia_build_main_dir() {
|
|||
mkdir -p "$MEDIA_DIRECTORY/$user/eBook"
|
||||
ln -sfn "$MEDIA_DIRECTORY/share" "$MEDIA_DIRECTORY/$user/Share"
|
||||
# Création du lien symbolique dans le home de l'utilisateur.
|
||||
ln -sfn "$MEDIA_DIRECTORY/$user" "/home/$user/Multimedia"
|
||||
#link will only be created if the home directory of the user exists and if it's located in '/home' folder
|
||||
local user_home="$(getent passwd $user | cut -d: -f6 | grep '^/home/')"
|
||||
if [[ -d "$user_home" ]]; then
|
||||
ln -sfn "$MEDIA_DIRECTORY/$user" "$user_home/Multimedia"
|
||||
fi
|
||||
# Propriétaires des dossiers utilisateurs.
|
||||
chown -R $user "$MEDIA_DIRECTORY/$user"
|
||||
done
|
||||
|
|
|
@ -362,8 +362,17 @@ ynh_permission_has_user() {
|
|||
return 1
|
||||
fi
|
||||
|
||||
yunohost user permission info "$app.$permission" --output-as json --quiet \
|
||||
| jq -e --arg user $user '.corresponding_users | index($user)' >/dev/null
|
||||
# Check both allowed and corresponding_users sections in the json
|
||||
for section in "allowed" "corresponding_users"
|
||||
do
|
||||
if yunohost user permission info "$app.$permission" --output-as json --quiet \
|
||||
| jq -e --arg user $user --arg section $section '.[$section] | index($user)' >/dev/null
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if a legacy permissions exist
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
set -e
|
||||
|
||||
services_path="/etc/yunohost/services.yml"
|
||||
|
||||
do_init_regen() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "You must be root to run this script" 1>&2
|
||||
|
@ -19,8 +17,6 @@ do_init_regen() {
|
|||
|| echo "yunohost.org" > /etc/yunohost/current_host
|
||||
|
||||
# copy default services and firewall
|
||||
[[ -f $services_path ]] \
|
||||
|| cp services.yml "$services_path"
|
||||
[[ -f /etc/yunohost/firewall.yml ]] \
|
||||
|| cp firewall.yml /etc/yunohost/firewall.yml
|
||||
|
||||
|
@ -49,6 +45,9 @@ do_init_regen() {
|
|||
chmod 644 /etc/ssowat/conf.json.persistent
|
||||
chown root:root /etc/ssowat/conf.json.persistent
|
||||
|
||||
# Empty service conf
|
||||
touch /etc/yunohost/services.yml
|
||||
|
||||
mkdir -p /var/cache/yunohost/repo
|
||||
chown root:root /var/cache/yunohost
|
||||
chmod 700 /var/cache/yunohost
|
||||
|
@ -59,25 +58,9 @@ do_pre_regen() {
|
|||
|
||||
cd /usr/share/yunohost/templates/yunohost
|
||||
|
||||
# update services.yml
|
||||
if [[ -f $services_path ]]; then
|
||||
tmp_services_path="${services_path}-tmp"
|
||||
new_services_path="${services_path}-new"
|
||||
cp "$services_path" "$tmp_services_path"
|
||||
_update_services "$new_services_path" || {
|
||||
mv "$tmp_services_path" "$services_path"
|
||||
exit 1
|
||||
}
|
||||
if [[ -f $new_services_path ]]; then
|
||||
# replace services.yml with new one
|
||||
mv "$new_services_path" "$services_path"
|
||||
mv "$tmp_services_path" "${services_path}-old"
|
||||
else
|
||||
rm -f "$tmp_services_path"
|
||||
fi
|
||||
else
|
||||
cp services.yml /etc/yunohost/services.yml
|
||||
fi
|
||||
# Legacy code that can be removed once on bullseye
|
||||
touch /etc/yunohost/services.yml
|
||||
yunohost tools shell -c "from yunohost.service import _get_services, _save_services; _save_services(_get_services())"
|
||||
|
||||
mkdir -p $pending_dir/etc/cron.d/
|
||||
mkdir -p $pending_dir/etc/cron.daily/
|
||||
|
@ -140,6 +123,14 @@ HandleLidSwitchDocked=ignore
|
|||
HandleLidSwitchExternalPower=ignore
|
||||
EOF
|
||||
|
||||
mkdir -p ${pending_dir}/etc/systemd/
|
||||
if [[ "$(yunohost settings get 'security.experimental.enabled')" == "True" ]]
|
||||
then
|
||||
cp proc-hidepid.service ${pending_dir}/etc/systemd/system/proc-hidepid.service
|
||||
else
|
||||
touch ${pending_dir}/etc/systemd/system/proc-hidepid.service
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
|
@ -199,58 +190,13 @@ do_post_regen() {
|
|||
# Propagates changes in systemd service config overrides
|
||||
[[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || { systemctl daemon-reload; systemctl restart ntp; }
|
||||
[[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload
|
||||
}
|
||||
|
||||
_update_services() {
|
||||
python3 - << EOF
|
||||
import yaml
|
||||
|
||||
|
||||
with open('services.yml') as f:
|
||||
new_services = yaml.safe_load(f)
|
||||
|
||||
with open('/etc/yunohost/services.yml') as f:
|
||||
services = yaml.safe_load(f) or {}
|
||||
|
||||
updated = False
|
||||
|
||||
|
||||
for service, conf in new_services.items():
|
||||
# remove service with empty conf
|
||||
if conf is None:
|
||||
if service in services:
|
||||
print("removing '{0}' from services".format(service))
|
||||
del services[service]
|
||||
updated = True
|
||||
|
||||
# add new service
|
||||
elif not services.get(service, None):
|
||||
print("adding '{0}' to services".format(service))
|
||||
services[service] = conf
|
||||
updated = True
|
||||
|
||||
# update service conf
|
||||
else:
|
||||
conffiles = services[service].pop('conffiles', {})
|
||||
|
||||
# status need to be removed
|
||||
if "status" not in conf and "status" in services[service]:
|
||||
print("update '{0}' service status access".format(service))
|
||||
del services[service]["status"]
|
||||
updated = True
|
||||
|
||||
if services[service] != conf:
|
||||
print("update '{0}' service".format(service))
|
||||
services[service].update(conf)
|
||||
updated = True
|
||||
|
||||
if conffiles:
|
||||
services[service]['conffiles'] = conffiles
|
||||
|
||||
if updated:
|
||||
with open('/etc/yunohost/services.yml-new', 'w') as f:
|
||||
yaml.safe_dump(services, f, default_flow_style=False)
|
||||
EOF
|
||||
[[ ! "$regen_conf_files" =~ "login.conf.d/ynh-override.conf" ]] || systemctl daemon-reload
|
||||
if [[ "$regen_conf_files" =~ "proc-hidepid.service" ]]
|
||||
then
|
||||
systemctl daemon-reload
|
||||
action=$([[ -e /etc/systemd/system/proc-hidepid.service ]] && echo 'enable' || echo 'disable')
|
||||
systemctl $action proc-hidepid --quiet --now
|
||||
fi
|
||||
}
|
||||
|
||||
FORCE=${2:-0}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
set -e
|
||||
|
||||
tmp_backup_dir_file="/tmp/slapd-backup-dir.txt"
|
||||
tmp_backup_dir_file="/root/slapd-backup-dir.txt"
|
||||
|
||||
config="/usr/share/yunohost/templates/slapd/config.ldif"
|
||||
db_init="/usr/share/yunohost/templates/slapd/db_init.ldif"
|
||||
|
|
|
@ -17,19 +17,16 @@ Pin-Priority: -1" >> "${pending_dir}/etc/apt/preferences.d/extra_php_version"
|
|||
done
|
||||
|
||||
echo "
|
||||
# Yes !
|
||||
# This is what's preventing you from installing apache2 !
|
||||
#
|
||||
# Maybe take two fucking minutes to realize that if you try to install
|
||||
# apache2, this will break nginx and break the entire YunoHost ecosystem.
|
||||
# on your server.
|
||||
#
|
||||
# So, *NO*
|
||||
# DO NOT do this.
|
||||
# DO NOT remove these lines.
|
||||
#
|
||||
# I warned you. I WARNED YOU! But did you listen to me?
|
||||
# Oooooh, noooo. You knew it all, didn't you?
|
||||
|
||||
# PLEASE READ THIS WARNING AND DON'T EDIT THIS FILE
|
||||
|
||||
# You are probably reading this file because you tried to install apache2 or
|
||||
# bind9. These 2 packages conflict with YunoHost.
|
||||
|
||||
# Installing apache2 will break nginx and break the entire YunoHost ecosystem
|
||||
# on your server, therefore don't remove those lines!
|
||||
|
||||
# You have been warned.
|
||||
|
||||
Package: apache2
|
||||
Pin: release *
|
||||
|
@ -39,9 +36,9 @@ Package: apache2-bin
|
|||
Pin: release *
|
||||
Pin-Priority: -1
|
||||
|
||||
# Also yes, bind9 will conflict with dnsmasq.
|
||||
# Same story than for apache2.
|
||||
# Don't fucking install it.
|
||||
# Also bind9 will conflict with dnsmasq.
|
||||
# Same story as for apache2.
|
||||
# Don't install it, don't remove those lines.
|
||||
|
||||
Package: bind9
|
||||
Pin: release *
|
||||
|
|
|
@ -61,6 +61,7 @@ do_pre_regen() {
|
|||
|
||||
# Support different strategy for security configurations
|
||||
export compatibility="$(yunohost settings get 'security.nginx.compatibility')"
|
||||
export experimental="$(yunohost settings get 'security.experimental.enabled')"
|
||||
ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc"
|
||||
|
||||
cert_status=$(yunohost domain cert-status --json)
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
do_pre_regen() {
|
||||
pending_dir=$1
|
||||
|
||||
cd /usr/share/yunohost/templates/avahi-daemon
|
||||
|
||||
install -D -m 644 avahi-daemon.conf \
|
||||
"${pending_dir}/etc/avahi/avahi-daemon.conf"
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
regen_conf_files=$1
|
||||
|
||||
[[ -z "$regen_conf_files" ]] \
|
||||
|| systemctl restart avahi-daemon
|
||||
}
|
||||
|
||||
FORCE=${2:-0}
|
||||
DRY_RUN=${3:-0}
|
||||
|
||||
case "$1" in
|
||||
pre)
|
||||
do_pre_regen $4
|
||||
;;
|
||||
post)
|
||||
do_post_regen $4
|
||||
;;
|
||||
*)
|
||||
echo "hook called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
83
data/hooks/conf_regen/37-mdns
Executable file
83
data/hooks/conf_regen/37-mdns
Executable file
|
@ -0,0 +1,83 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
_generate_config() {
|
||||
echo "domains:"
|
||||
echo " - yunohost.local"
|
||||
for domain in $YNH_DOMAINS
|
||||
do
|
||||
# Only keep .local domains (don't keep
|
||||
[[ "$domain" =~ [^.]+\.[^.]+\.local$ ]] && echo "Subdomain $domain cannot be handled by Bonjour/Zeroconf/mDNS" >&2
|
||||
[[ "$domain" =~ ^[^.]+\.local$ ]] || continue
|
||||
echo " - $domain"
|
||||
done
|
||||
|
||||
echo "interfaces:"
|
||||
local_network_interfaces="$(ip --brief a | grep ' 10\.\| 192\.168\.' | awk '{print $1}')"
|
||||
for interface in $local_network_interfaces
|
||||
do
|
||||
echo " - $interface"
|
||||
done
|
||||
}
|
||||
|
||||
do_init_regen() {
|
||||
do_pre_regen
|
||||
do_post_regen /etc/systemd/system/yunomdns.service
|
||||
systemctl enable yunomdns
|
||||
}
|
||||
|
||||
do_pre_regen() {
|
||||
pending_dir="$1"
|
||||
|
||||
cd /usr/share/yunohost/templates/mdns
|
||||
mkdir -p ${pending_dir}/etc/systemd/system/
|
||||
cp yunomdns.service ${pending_dir}/etc/systemd/system/
|
||||
|
||||
getent passwd mdns &>/dev/null || useradd --no-create-home --shell /usr/sbin/nologin --system --user-group mdns
|
||||
|
||||
mkdir -p ${pending_dir}/etc/yunohost
|
||||
_generate_config > ${pending_dir}/etc/yunohost/mdns.yml
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
regen_conf_files="$1"
|
||||
|
||||
chown mdns:mdns /etc/yunohost/mdns.yml
|
||||
|
||||
# If we changed the systemd ynh-override conf
|
||||
if echo "$regen_conf_files" | sed 's/,/\n/g' | grep -q "^/etc/systemd/system/yunomdns.service$"
|
||||
then
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
|
||||
# Legacy stuff to enable the new yunomdns service on legacy systems
|
||||
if [[ -e /etc/avahi/avahi-daemon.conf ]] && grep -q 'yunohost' /etc/avahi/avahi-daemon.conf
|
||||
then
|
||||
systemctl enable yunomdns
|
||||
fi
|
||||
|
||||
[[ -z "$regen_conf_files" ]] \
|
||||
|| systemctl restart yunomdns
|
||||
}
|
||||
|
||||
FORCE=${2:-0}
|
||||
DRY_RUN=${3:-0}
|
||||
|
||||
case "$1" in
|
||||
pre)
|
||||
do_pre_regen $4
|
||||
;;
|
||||
post)
|
||||
do_post_regen $4
|
||||
;;
|
||||
init)
|
||||
do_init_regen
|
||||
;;
|
||||
*)
|
||||
echo "hook called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -13,6 +13,7 @@ from yunohost.diagnosis import Diagnoser
|
|||
from yunohost.domain import domain_list, _build_dns_conf, _get_maindomain
|
||||
|
||||
YNH_DYNDNS_DOMAINS = ["nohost.me", "noho.st", "ynh.fr"]
|
||||
SPECIAL_USE_TLDS = ["local", "localhost", "onion", "test"]
|
||||
|
||||
|
||||
class DNSRecordsDiagnoser(Diagnoser):
|
||||
|
@ -29,8 +30,14 @@ class DNSRecordsDiagnoser(Diagnoser):
|
|||
for domain in all_domains:
|
||||
self.logger_debug("Diagnosing DNS conf for %s" % domain)
|
||||
is_subdomain = domain.split(".", 1)[1] in all_domains
|
||||
is_specialusedomain = any(
|
||||
domain.endswith("." + tld) for tld in SPECIAL_USE_TLDS
|
||||
)
|
||||
for report in self.check_domain(
|
||||
domain, domain == main_domain, is_subdomain=is_subdomain
|
||||
domain,
|
||||
domain == main_domain,
|
||||
is_subdomain=is_subdomain,
|
||||
is_specialusedomain=is_specialusedomain,
|
||||
):
|
||||
yield report
|
||||
|
||||
|
@ -48,7 +55,7 @@ class DNSRecordsDiagnoser(Diagnoser):
|
|||
for report in self.check_expiration_date(domains_from_registrar):
|
||||
yield report
|
||||
|
||||
def check_domain(self, domain, is_main_domain, is_subdomain):
|
||||
def check_domain(self, domain, is_main_domain, is_subdomain, is_specialusedomain):
|
||||
|
||||
expected_configuration = _build_dns_conf(
|
||||
domain, include_empty_AAAA_if_no_ipv6=True
|
||||
|
@ -59,6 +66,15 @@ class DNSRecordsDiagnoser(Diagnoser):
|
|||
if is_subdomain:
|
||||
categories = ["basic"]
|
||||
|
||||
if is_specialusedomain:
|
||||
categories = []
|
||||
yield dict(
|
||||
meta={"domain": domain},
|
||||
data={},
|
||||
status="INFO",
|
||||
summary="diagnosis_dns_specialusedomain",
|
||||
)
|
||||
|
||||
for category in categories:
|
||||
|
||||
records = expected_configuration[category]
|
||||
|
|
|
@ -34,6 +34,12 @@ class WebDiagnoser(Diagnoser):
|
|||
summary="diagnosis_http_nginx_conf_not_up_to_date",
|
||||
details=["diagnosis_http_nginx_conf_not_up_to_date_details"],
|
||||
)
|
||||
elif domain.endswith(".local"):
|
||||
yield dict(
|
||||
meta={"domain": domain},
|
||||
status="INFO",
|
||||
summary="diagnosis_http_localdomain",
|
||||
)
|
||||
else:
|
||||
domains_to_check.append(domain)
|
||||
|
||||
|
|
96
data/hooks/diagnosis/80-apps.py
Normal file
96
data/hooks/diagnosis/80-apps.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
|
||||
from yunohost.app import app_list
|
||||
|
||||
from yunohost.diagnosis import Diagnoser
|
||||
|
||||
|
||||
class AppDiagnoser(Diagnoser):
|
||||
|
||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||
cache_duration = 300
|
||||
dependencies = []
|
||||
|
||||
def run(self):
|
||||
|
||||
apps = app_list(full=True)["apps"]
|
||||
for app in apps:
|
||||
app["issues"] = list(self.issues(app))
|
||||
|
||||
if not any(app["issues"] for app in apps):
|
||||
yield dict(
|
||||
meta={"test": "apps"},
|
||||
status="SUCCESS",
|
||||
summary="diagnosis_apps_allgood",
|
||||
)
|
||||
else:
|
||||
for app in apps:
|
||||
|
||||
if not app["issues"]:
|
||||
continue
|
||||
|
||||
level = (
|
||||
"ERROR"
|
||||
if any(issue[0] == "error" for issue in app["issues"])
|
||||
else "WARNING"
|
||||
)
|
||||
|
||||
yield dict(
|
||||
meta={"test": "apps", "app": app["name"]},
|
||||
status=level,
|
||||
summary="diagnosis_apps_issue",
|
||||
details=[issue[1] for issue in app["issues"]],
|
||||
)
|
||||
|
||||
def issues(self, app):
|
||||
|
||||
# Check quality level in catalog
|
||||
|
||||
if not app.get("from_catalog") or app["from_catalog"].get("state") != "working":
|
||||
yield ("error", "diagnosis_apps_not_in_app_catalog")
|
||||
elif (
|
||||
not isinstance(app["from_catalog"].get("level"), int)
|
||||
or app["from_catalog"]["level"] == 0
|
||||
):
|
||||
yield ("error", "diagnosis_apps_broken")
|
||||
elif app["from_catalog"]["level"] <= 4:
|
||||
yield ("warning", "diagnosis_apps_bad_quality")
|
||||
|
||||
# Check for super old, deprecated practices
|
||||
|
||||
yunohost_version_req = (
|
||||
app["manifest"].get("requirements", {}).get("yunohost", "").strip(">= ")
|
||||
)
|
||||
if yunohost_version_req.startswith("2."):
|
||||
yield ("error", "diagnosis_apps_outdated_ynh_requirement")
|
||||
|
||||
deprecated_helpers = [
|
||||
"yunohost app setting",
|
||||
"yunohost app checkurl",
|
||||
"yunohost app checkport",
|
||||
"yunohost app initdb",
|
||||
"yunohost tools port-available",
|
||||
]
|
||||
for deprecated_helper in deprecated_helpers:
|
||||
if (
|
||||
os.system(
|
||||
f"grep -nr -q '{deprecated_helper}' {app['setting_path']}/scripts/"
|
||||
)
|
||||
== 0
|
||||
):
|
||||
yield ("error", "diagnosis_apps_deprecated_practices")
|
||||
|
||||
old_arg_regex = r"^domain=\${?[0-9]"
|
||||
if (
|
||||
os.system(
|
||||
f"grep -q '{old_arg_regex}' {app['setting_path']}/scripts/install"
|
||||
)
|
||||
== 0
|
||||
):
|
||||
yield ("error", "diagnosis_apps_deprecated_practices")
|
||||
|
||||
|
||||
def main(args, env, loggers):
|
||||
return AppDiagnoser(args, env, loggers).diagnose()
|
|
@ -15,7 +15,11 @@ mkdir -p "$MEDIA_DIRECTORY/$user/Video"
|
|||
mkdir -p "$MEDIA_DIRECTORY/$user/eBook"
|
||||
ln -sfn "$MEDIA_DIRECTORY/share" "$MEDIA_DIRECTORY/$user/Share"
|
||||
# Création du lien symbolique dans le home de l'utilisateur.
|
||||
ln -sfn "$MEDIA_DIRECTORY/$user" "/home/$user/Multimedia"
|
||||
#link will only be created if the home directory of the user exists and if it's located in '/home' folder
|
||||
user_home="$(getent passwd $user | cut -d: -f6 | grep '^/home/')"
|
||||
if [[ -d "$user_home" ]]; then
|
||||
ln -sfn "$MEDIA_DIRECTORY/$user" "$user_home/Multimedia"
|
||||
fi
|
||||
# Propriétaires des dossiers utilisateurs.
|
||||
chown -R $user "$MEDIA_DIRECTORY/$user"
|
||||
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
# This file is part of avahi.
|
||||
#
|
||||
# avahi is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# avahi is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
# License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with avahi; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
# USA.
|
||||
|
||||
# See avahi-daemon.conf(5) for more information on this configuration
|
||||
# file!
|
||||
|
||||
[server]
|
||||
host-name=yunohost
|
||||
domain-name=local
|
||||
#browse-domains=0pointer.de, zeroconf.org
|
||||
use-ipv4=yes
|
||||
use-ipv6=yes
|
||||
#allow-interfaces=eth0
|
||||
#deny-interfaces=eth1
|
||||
#check-response-ttl=no
|
||||
#use-iff-running=no
|
||||
#enable-dbus=yes
|
||||
#disallow-other-stacks=no
|
||||
#allow-point-to-point=no
|
||||
#cache-entries-max=4096
|
||||
#clients-max=4096
|
||||
#objects-per-client-max=1024
|
||||
#entries-per-entry-group-max=32
|
||||
ratelimit-interval-usec=1000000
|
||||
ratelimit-burst=1000
|
||||
|
||||
[wide-area]
|
||||
enable-wide-area=yes
|
||||
|
||||
[publish]
|
||||
#disable-publishing=no
|
||||
#disable-user-service-publishing=no
|
||||
#add-service-cookie=no
|
||||
#publish-addresses=yes
|
||||
#publish-hinfo=yes
|
||||
#publish-workstation=yes
|
||||
#publish-domain=yes
|
||||
#publish-dns-servers=192.168.50.1, 192.168.50.2
|
||||
#publish-resolv-conf-dns-servers=yes
|
||||
#publish-aaaa-on-ipv4=yes
|
||||
#publish-a-on-ipv6=no
|
||||
|
||||
[reflector]
|
||||
#enable-reflector=no
|
||||
#reflect-ipv=no
|
||||
|
||||
[rlimits]
|
||||
#rlimit-as=
|
||||
rlimit-core=0
|
||||
rlimit-data=4194304
|
||||
rlimit-fsize=0
|
||||
rlimit-nofile=768
|
||||
rlimit-stack=4194304
|
||||
rlimit-nproc=3
|
13
data/templates/mdns/yunomdns.service
Normal file
13
data/templates/mdns/yunomdns.service
Normal file
|
@ -0,0 +1,13 @@
|
|||
[Unit]
|
||||
Description=YunoHost mDNS service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=mdns
|
||||
Group=mdns
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/yunomdns
|
||||
StandardOutput=syslog
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
|
@ -30,7 +30,7 @@ skip-external-locking
|
|||
key_buffer_size = 16K
|
||||
max_allowed_packet = 16M
|
||||
table_open_cache = 4
|
||||
sort_buffer_size = 64K
|
||||
sort_buffer_size = 256K
|
||||
read_buffer_size = 256K
|
||||
read_rnd_buffer_size = 256K
|
||||
net_buffer_length = 2K
|
||||
|
|
|
@ -25,7 +25,11 @@ ssl_dhparam /usr/share/yunohost/other/ffdhe2048.pem;
|
|||
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
|
||||
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
|
||||
# https://observatory.mozilla.org/
|
||||
{% if experimental == "True" %}
|
||||
more_set_headers "Content-Security-Policy : upgrade-insecure-requests; default-src https: data:";
|
||||
{% else %}
|
||||
more_set_headers "Content-Security-Policy : upgrade-insecure-requests";
|
||||
{% endif %}
|
||||
more_set_headers "Content-Security-Policy-Report-Only : default-src https: data: 'unsafe-inline' 'unsafe-eval' ";
|
||||
more_set_headers "X-Content-Type-Options : nosniff";
|
||||
more_set_headers "X-XSS-Protection : 1; mode=block";
|
||||
|
@ -34,7 +38,13 @@ more_set_headers "X-Permitted-Cross-Domain-Policies : none";
|
|||
more_set_headers "X-Frame-Options : SAMEORIGIN";
|
||||
|
||||
# Disable the disaster privacy thing that is FLoC
|
||||
{% if experimental == "True" %}
|
||||
more_set_headers "Permissions-Policy : fullscreen=(), geolocation=(), payment=(), accelerometer=(), battery=(), magnetometer=(), usb=(), interest-cohort=()";
|
||||
# Force HTTPOnly and Secure for all cookies
|
||||
proxy_cookie_path ~$ "; HTTPOnly; Secure;";
|
||||
{% else %}
|
||||
more_set_headers "Permissions-Policy : interest-cohort=()";
|
||||
{% endif %}
|
||||
|
||||
# Disable gzip to protect against BREACH
|
||||
# Read https://trac.nginx.org/nginx/ticket/1720 (text/html cannot be disabled!)
|
||||
|
|
14
data/templates/yunohost/proc-hidepid.service
Normal file
14
data/templates/yunohost/proc-hidepid.service
Normal file
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=Mounts /proc with hidepid=2
|
||||
DefaultDependencies=no
|
||||
Before=sysinit.target
|
||||
Requires=local-fs.target
|
||||
After=local-fs.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/mount -o remount,nosuid,nodev,noexec,hidepid=2 /proc
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=sysinit.target
|
|
@ -1,4 +1,3 @@
|
|||
avahi-daemon: {}
|
||||
dnsmasq:
|
||||
test_conf: dnsmasq --test
|
||||
dovecot:
|
||||
|
@ -52,6 +51,8 @@ yunohost-firewall:
|
|||
need_lock: true
|
||||
test_status: iptables -S | grep "^-A INPUT" | grep " --dport" | grep -q ACCEPT
|
||||
category: security
|
||||
yunomdns:
|
||||
category: mdns
|
||||
glances: null
|
||||
nsswitch: null
|
||||
ssl: null
|
||||
|
@ -69,3 +70,4 @@ php5-fpm: null
|
|||
php7.0-fpm: null
|
||||
php7.3-fpm:
|
||||
nslcd: null
|
||||
avahi-daemon: null
|
||||
|
|
21
debian/changelog
vendored
21
debian/changelog
vendored
|
@ -4,6 +4,27 @@ yunohost (11.0.0~alpha) unstable; urgency=low
|
|||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 05 Feb 2021 00:02:38 +0100
|
||||
|
||||
yunohost (4.2.8.1) stable; urgency=low
|
||||
|
||||
- [fix] Safer location for slapd backup during hdb/mdb migration (3c646b3d)
|
||||
|
||||
Thanks to all contributors <3 ! (ljf)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 27 Aug 2021 01:32:16 +0200
|
||||
|
||||
yunohost (4.2.8) stable; urgency=low
|
||||
|
||||
- [fix] ynh_permission_has_user not behaving properly when checking if a group is allowed (f0590907)
|
||||
- [enh] use yaml safeloader everywhere ([#1287](https://github.com/YunoHost/yunohost/pull/1287))
|
||||
- [enh] Add --no-safety-backup option to "yunohost app upgrade" ([#1286](https://github.com/YunoHost/yunohost/pull/1286))
|
||||
- [enh] Add --purge option to "yunohost app remove" ([#1285](https://github.com/YunoHost/yunohost/pull/1285))
|
||||
- [enh] Multimedia helper: check that home folder exists ([#1255](https://github.com/YunoHost/yunohost/pull/1255))
|
||||
- [i18n] Translations updated for French, Galician, German, Portuguese
|
||||
|
||||
Thanks to all contributors <3 ! (José M, Kay0u, Krakinou, ljf, Luca, mifegui, ppr, sagessylu)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 19 Aug 2021 19:11:19 +0200
|
||||
|
||||
yunohost (4.2.7) stable; urgency=low
|
||||
|
||||
Notable changes:
|
||||
|
|
3
debian/control
vendored
3
debian/control
vendored
|
@ -14,6 +14,7 @@ Depends: ${python3:Depends}, ${misc:Depends}
|
|||
, python3-psutil, python3-requests, python3-dnspython, python3-openssl
|
||||
, python3-miniupnpc, python3-dbus, python3-jinja2
|
||||
, python3-toml, python3-packaging, python3-publicsuffix2
|
||||
, python3-ldap, python3-zeroconf
|
||||
, python-is-python3
|
||||
, nginx, nginx-extras (>=1.18)
|
||||
, apt, apt-transport-https, apt-utils, dirmngr
|
||||
|
@ -22,7 +23,7 @@ Depends: ${python3:Depends}, ${misc:Depends}
|
|||
, openssh-server, iptables, fail2ban, dnsutils, bind9utils
|
||||
, openssl, ca-certificates, netcat-openbsd, iproute2
|
||||
, slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd
|
||||
, dnsmasq, avahi-daemon, libnss-mdns, resolvconf, libnss-myhostname
|
||||
, dnsmasq, resolvconf, libnss-myhostname
|
||||
, postfix, postfix-ldap, postfix-policyd-spf-perl, postfix-pcre
|
||||
, dovecot-core, dovecot-ldap, dovecot-lmtpd, dovecot-managesieved, dovecot-antispam
|
||||
, rspamd, opendkim-tools, postsrsd, procmail, mailutils
|
||||
|
|
1
debian/postinst
vendored
1
debian/postinst
vendored
|
@ -18,6 +18,7 @@ do_configure() {
|
|||
bash /usr/share/yunohost/hooks/conf_regen/46-nsswitch init
|
||||
bash /usr/share/yunohost/hooks/conf_regen/06-slapd init
|
||||
bash /usr/share/yunohost/hooks/conf_regen/15-nginx init
|
||||
bash /usr/share/yunohost/hooks/conf_regen/37-mdns init
|
||||
fi
|
||||
else
|
||||
echo "Regenerating configuration, this might take a while..."
|
||||
|
|
|
@ -26,7 +26,7 @@ ACTIONSMAP_FILE = os.path.join(THIS_SCRIPT_DIR, "../data/actionsmap/yunohost.yml
|
|||
|
||||
|
||||
def ordered_yaml_load(stream):
|
||||
class OrderedLoader(yaml.Loader):
|
||||
class OrderedLoader(yaml.SafeLoader):
|
||||
pass
|
||||
|
||||
OrderedLoader.add_constructor(
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
"yunohost_installing": "عملية تنصيب يونوهوست جارية …",
|
||||
"yunohost_not_installed": "إنَّ واي يونوهوست ليس مُنَصَّب أو هو مثبت حاليا بشكل خاطئ. قم بتنفيذ الأمر 'yunohost tools postinstall'",
|
||||
"migrations_list_conflict_pending_done": "لا يمكنك استخدام --previous و --done معًا على نفس سطر الأوامر.",
|
||||
"service_description_avahi-daemon": "يسمح لك بالنفاذ إلى خادومك عبر الشبكة المحلية باستخدام yunohost.local",
|
||||
"service_description_metronome": "يُدير حسابات الدردشة الفورية XMPP",
|
||||
"service_description_nginx": "يقوم بتوفير النفاذ و السماح بالوصول إلى كافة مواقع الويب المستضافة على خادومك",
|
||||
"service_description_postfix": "يقوم بإرسال و تلقي الرسائل البريدية الإلكترونية",
|
||||
|
|
|
@ -283,7 +283,6 @@
|
|||
"service_already_started": "El servei «{service}» ja està funcionant",
|
||||
"service_already_stopped": "Ja s'ha aturat el servei «{service}»",
|
||||
"service_cmd_exec_failed": "No s'ha pogut executar l'ordre «{command}»",
|
||||
"service_description_avahi-daemon": "Permet accedir al servidor via «yunohost.local» en la xarxa local",
|
||||
"service_description_dnsmasq": "Gestiona la resolució del nom de domini (DNS)",
|
||||
"service_description_dovecot": "Permet als clients de correu accedir/recuperar correus (via IMAP i POP3)",
|
||||
"service_description_fail2ban": "Protegeix contra els atacs de força bruta i a altres atacs provinents d'Internet",
|
||||
|
|
1
locales/ckb.json
Normal file
1
locales/ckb.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -124,7 +124,7 @@
|
|||
"upnp_dev_not_found": "Es konnten keine UPnP Geräte gefunden werden",
|
||||
"upnp_disabled": "UPnP deaktiviert",
|
||||
"upnp_enabled": "UPnP aktiviert",
|
||||
"upnp_port_open_failed": "UPnP Port konnte nicht geöffnet werden.",
|
||||
"upnp_port_open_failed": "Port konnte nicht via UPnP geöffnet werden",
|
||||
"user_created": "Benutzer erstellt",
|
||||
"user_creation_failed": "Benutzer konnte nicht erstellt werden {user}: {error}",
|
||||
"user_deleted": "Benutzer gelöscht",
|
||||
|
@ -378,7 +378,7 @@
|
|||
"diagnosis_mail_ehlo_wrong_details": "Die vom Remote-Diagnose-Server per IPv{ipversion} empfangene EHLO weicht von der Domäne Ihres Servers ab. <br>Empfangene EHLO: <code>{wrong_ehlo}</code><br>Erwartet: <code>{right_ehlo}</code> <br> Die geläufigste Ursache für dieses Problem ist, dass der Port 25 <a href='https://yunohost.org/isp_box_config'> nicht korrekt auf Ihren Server weitergeleitet wird</a>. Sie können sich zusätzlich auch versichern, dass keine Firewall oder Reverse-Proxy interferiert.",
|
||||
"diagnosis_mail_ehlo_bad_answer_details": "Das könnte daran liegen, dass anstelle Ihres Servers eine andere Maschine antwortet.",
|
||||
"ask_user_domain": "Domäne, welche für die E-Mail-Adresse und den XMPP-Account des Benutzers verwendet werden soll",
|
||||
"app_manifest_install_ask_is_public": "Soll diese Applikation für anonyme Benutzer sichtbar sein?",
|
||||
"app_manifest_install_ask_is_public": "Soll diese Applikation für anonyme Benutzer:innen sichtbar sein?",
|
||||
"app_manifest_install_ask_admin": "Wählen Sie einen Administrator für diese Applikation",
|
||||
"app_manifest_install_ask_path": "Wählen Sie den Pfad, in welchem die Applikation installiert werden soll",
|
||||
"diagnosis_mail_blacklist_listed_by": "Ihre IP-Adresse oder Domäne <code>{item}</code> ist auf der Blacklist auf {blacklist_name}",
|
||||
|
@ -528,7 +528,7 @@
|
|||
"migrations_no_such_migration": "Es existiert keine Migration genannt '{id}'",
|
||||
"migrations_running_forward": "Durchführen der Migrationen {id}...",
|
||||
"migrations_skip_migration": "Überspringe Migrationen {id}...",
|
||||
"password_too_simple_2": "Dieses Passwort gehört zu den meistverwendeten der Welt. Bitte nehmen Sie etwas einzigartigeres",
|
||||
"password_too_simple_2": "Das Passwort muss mindestens 8 Zeichen lang sein und Gross- sowie Kleinbuchstaben enthalten",
|
||||
"password_listed": "Dieses Passwort zählt zu den meistgenutzten Passwörtern der Welt. Bitte wähle ein anderes, einzigartigeres Passwort.",
|
||||
"operation_interrupted": "Wurde die Operation manuell unterbrochen?",
|
||||
"invalid_number": "Muss eine Zahl sein",
|
||||
|
@ -539,8 +539,8 @@
|
|||
"permission_already_allowed": "Die Gruppe '{group}' hat die Berechtigung '{permission}' bereits erhalten",
|
||||
"pattern_password_app": "Entschuldigen Sie bitte! Passwörter dürfen folgende Zeichen nicht enthalten: {forbidden_chars}",
|
||||
"pattern_email_forward": "Es muss sich um eine gültige E-Mail-Adresse handeln. Das Symbol '+' wird akzeptiert (zum Beispiel : maxmuster@beispiel.com oder maxmuster+yunohost@beispiel.com)",
|
||||
"password_too_simple_4": "Dass Passwort muss mindestens 12 Zeichen lang sein und Zahlen, Klein- und Grossbuchstaben und Sonderzeichen enthalten",
|
||||
"password_too_simple_3": "Das Passwort muss mindestens 8 Zeichen lang sein und Zahlen, Klein- und Grossbuchstaben und Sonderzeichen enthalten",
|
||||
"password_too_simple_4": "Das Passwort muss mindestens 12 Zeichen lang sein und Grossbuchstaben, Kleinbuchstaben, Zahlen und Sonderzeichen enthalten",
|
||||
"password_too_simple_3": "Das Passwort muss mindestens 8 Zeichen lang sein und Grossbuchstaben, Kleinbuchstaben, Zahlen und Sonderzeichen enthalten",
|
||||
"regenconf_file_manually_removed": "Die Konfigurationsdatei '{conf}' wurde manuell gelöscht und wird nicht erstellt",
|
||||
"regenconf_file_manually_modified": "Die Konfigurationsdatei '{conf}' wurde manuell bearbeitet und wird nicht aktualisiert",
|
||||
"regenconf_file_kept_back": "Die Konfigurationsdatei '{conf}' sollte von \"regen-conf\" (Kategorie {category}) gelöscht werden, wurde aber beibehalten.",
|
||||
|
@ -597,7 +597,6 @@
|
|||
"service_description_fail2ban": "Schützt gegen Brute-Force-Angriffe und andere Angriffe aus dem Internet",
|
||||
"service_description_dovecot": "Ermöglicht es E-Mail-Clients auf Konten zuzugreifen (IMAP und POP3)",
|
||||
"service_description_dnsmasq": "Verarbeitet die Auflösung des Domainnamens (DNS)",
|
||||
"service_description_avahi-daemon": "Erlaubt, den Server im lokalen Netz über 'yunohost.local' zu erreichen",
|
||||
"restore_backup_too_old": "Dieses Backup kann nicht wieder hergestellt werden, weil es von einer zu alten YunoHost Version stammt.",
|
||||
"service_description_slapd": "Speichert Benutzer, Domains und verbundene Informationen",
|
||||
"service_description_rspamd": "Spamfilter und andere E-Mail-Merkmale",
|
||||
|
@ -631,5 +630,9 @@
|
|||
"unknown_main_domain_path": "Unbekannte:r Domain oder Pfad für '{app}'. Du musst eine Domain und einen Pfad setzen, um die URL für Berechtigungen zu setzen.",
|
||||
"yunohost_postinstall_end_tip": "Post-install ist fertig! Um das Setup abzuschliessen, wird empfohlen:\n - einen ersten Benutzer über den Bereich 'Benutzer*in' im Adminbereich hinzuzufügen (oder mit 'yunohost user create <username>' in der Kommandezeile);\n - mögliche Fehler zu diagnostizieren über den Bereich 'Diagnose' im Adminbereich (oder mit 'yunohost diagnosis run' in der Kommandozeile;\n - Die Abschnitte 'Install YunoHost' und 'Geführte Tour' im Administratorenhandbuch zu lesen: https://yunohost.org/admindoc.",
|
||||
"user_already_exists": "Der Benutzer '{user}' ist bereits vorhanden",
|
||||
"update_apt_cache_warning": "Beim Versuch den Cache für APT (Debians Paketmanager) zu aktualisieren, ist etwas schief gelaufen. Hier ist ein Dump der Zeilen aus sources.list, die Ihnen vielleicht dabei helfen, das Problem zu identifizieren:\n{sourceslist}"
|
||||
"update_apt_cache_warning": "Beim Versuch den Cache für APT (Debians Paketmanager) zu aktualisieren, ist etwas schief gelaufen. Hier ist ein Dump der Zeilen aus sources.list, die Ihnen vielleicht dabei helfen, das Problem zu identifizieren:\n{sourceslist}",
|
||||
"global_settings_setting_security_webadmin_allowlist": "IP-Adressen, die auf die Verwaltungsseite zugreifen dürfen. Kommasepariert.",
|
||||
"global_settings_setting_security_webadmin_allowlist_enabled": "Erlaube nur bestimmten IP-Adressen den Zugriff auf die Verwaltungsseite.",
|
||||
"disk_space_not_sufficient_update": "Es ist nicht genügend Speicherplatz frei, um diese Applikation zu aktuallisieren",
|
||||
"disk_space_not_sufficient_install": "Es ist nicht genügend Speicherplatz frei, um diese Applikation zu installieren"
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
"app_location_unavailable": "This URL is either unavailable, or conflicts with the already installed app(s):\n{apps}",
|
||||
"app_manifest_invalid": "Something is wrong with the app manifest: {error}",
|
||||
"app_manifest_install_ask_domain": "Choose the domain where this app should be installed",
|
||||
"app_manifest_install_ask_path": "Choose the path where this app should be installed",
|
||||
"app_manifest_install_ask_path": "Choose the URL path (after the domain) where this app should be installed",
|
||||
"app_manifest_install_ask_password": "Choose an administration password for this app",
|
||||
"app_manifest_install_ask_admin": "Choose an administrator user for this app",
|
||||
"app_manifest_install_ask_is_public": "Should this app be exposed to anonymous visitors?",
|
||||
|
@ -183,6 +183,7 @@
|
|||
"diagnosis_dns_discrepancy": "The following DNS record does not seem to follow the recommended configuration:<br>Type: <code>{type}</code><br>Name: <code>{name}</code><br>Current value: <code>{current}</code><br>Expected value: <code>{value}</code>",
|
||||
"diagnosis_dns_point_to_doc": "Please check the documentation at <a href='https://yunohost.org/dns_config'>https://yunohost.org/dns_config</a> if you need help about configuring DNS records.",
|
||||
"diagnosis_dns_try_dyndns_update_force": "This domain's DNS configuration should automatically be managed by YunoHost. If that's not the case, you can try to force an update using <cmd>yunohost dyndns update --force</cmd>.",
|
||||
"diagnosis_dns_specialusedomain": "Domain {domain} is based on a special-use top-level domain (TLD) and is therefore not expected to have actual DNS records.",
|
||||
"diagnosis_domain_expiration_not_found": "Unable to check the expiration date for some domains",
|
||||
"diagnosis_domain_not_found_details": "The domain {domain} doesn't exist in WHOIS database or is expired!",
|
||||
"diagnosis_domain_expiration_not_found_details": "The WHOIS information for domain {domain} doesn't seem to contain the information about the expiration date?",
|
||||
|
@ -248,6 +249,14 @@
|
|||
"diagnosis_description_web": "Web",
|
||||
"diagnosis_description_mail": "Email",
|
||||
"diagnosis_description_regenconf": "System configurations",
|
||||
"diagnosis_description_apps": "Applications",
|
||||
"diagnosis_apps_allgood": "All installed apps respect basic packaging practices",
|
||||
"diagnosis_apps_issue": "An issue was found for app {app}",
|
||||
"diagnosis_apps_not_in_app_catalog": "This application is not in YunoHost's application catalog. If it was in the past and got removed, you should consider uninstalling this app as it won't receive upgrade, and may compromise the integrity and security of your system.",
|
||||
"diagnosis_apps_broken": "This application is currently flagged as broken on YunoHost's application catalog. This may be a temporary issue while the maintainers attempt to fix the issue. In the meantime, upgrading this app is disabled.",
|
||||
"diagnosis_apps_bad_quality": "This application is currently flagged as broken on YunoHost's application catalog. This may be a temporary issue while the maintainers attempt to fix the issue. In the meantime, upgrading this app is disabled.",
|
||||
"diagnosis_apps_outdated_ynh_requirement": "This app's installed version only requires yunohost >= 2.x, which tends to indicate that it's not up to date with recommended packaging practices and helpers. You should really consider upgrading it.",
|
||||
"diagnosis_apps_deprecated_practices": "This app's installed version still uses some super-old deprecated packaging practices. You should really consider upgrading it.",
|
||||
"diagnosis_ports_could_not_diagnose": "Could not diagnose if ports are reachable from outside in IPv{ipversion}.",
|
||||
"diagnosis_ports_could_not_diagnose_details": "Error: {error}",
|
||||
"diagnosis_ports_unreachable": "Port {port} is not reachable from outside.",
|
||||
|
@ -259,6 +268,7 @@
|
|||
"diagnosis_http_hairpinning_issue_details": "This is probably because of your ISP box / router. As a result, people from outside your local network will be able to access your server as expected, but not people from inside the local network (like you, probably?) when using the domain name or global IP. You may be able to improve the situation by having a look at <a href='https://yunohost.org/dns_local_network'>https://yunohost.org/dns_local_network</a>",
|
||||
"diagnosis_http_could_not_diagnose": "Could not diagnose if domains are reachable from outside in IPv{ipversion}.",
|
||||
"diagnosis_http_could_not_diagnose_details": "Error: {error}",
|
||||
"diagnosis_http_localdomain": "Domain {domain}, with a .local TLD, is not expected to be reached from outside the local network.",
|
||||
"diagnosis_http_ok": "Domain {domain} is reachable through HTTP from outside the local network.",
|
||||
"diagnosis_http_timeout": "Timed-out while trying to contact your server from outside. It appears to be unreachable.<br>1. The most common cause for this issue is that port 80 (and 443) <a href='https://yunohost.org/isp_box_config'>are not correctly forwarded to your server</a>.<br>2. You should also make sure that the service nginx is running<br>3. On more complex setups: make sure that no firewall or reverse-proxy is interfering.",
|
||||
"diagnosis_http_connection_error": "Connection error: could not connect to the requested domain, it's very likely unreachable.",
|
||||
|
@ -340,6 +350,7 @@
|
|||
"global_settings_setting_smtp_relay_password": "SMTP relay host password",
|
||||
"global_settings_setting_security_webadmin_allowlist_enabled": "Allow only some IPs to access the webadmin.",
|
||||
"global_settings_setting_security_webadmin_allowlist": "IP adresses allowed to access the webadmin. Comma-separated.",
|
||||
"global_settings_setting_security_experimental_enabled": "Enable experimental security features (don't enable this if you don't know what you're doing!)",
|
||||
"global_settings_setting_backup_compress_tar_archives": "When creating new backups, compress the archives (.tar.gz) instead of uncompressed archives (.tar). N.B. : enabling this option means create lighter backup archives, but the initial backup procedure will be significantly longer and heavy on CPU.",
|
||||
"global_settings_unknown_type": "Unexpected situation, the setting {setting} appears to have the type {unknown_type} but it is not a type supported by the system.",
|
||||
"good_practices_about_admin_password": "You are now about to define a new administration password. The password should be at least 8 characters long—though it is good practice to use a longer password (i.e. a passphrase) and/or to use a variation of characters (uppercase, lowercase, digits and special characters).",
|
||||
|
@ -369,6 +380,8 @@
|
|||
"invalid_regex": "Invalid regex:'{regex}'",
|
||||
"ip6tables_unavailable": "You cannot play with ip6tables here. You are either in a container or your kernel does not support it",
|
||||
"iptables_unavailable": "You cannot play with iptables here. You are either in a container or your kernel does not support it",
|
||||
"ldap_server_down": "Unable to reach LDAP server",
|
||||
"ldap_server_is_down_restart_it": "The LDAP service is down, attempt to restart it...",
|
||||
"log_corrupted_md_file": "The YAML metadata file associated with logs is damaged: '{md_file}\nError: {error}'",
|
||||
"log_link_to_log": "Full log of this operation: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_help_to_get_log": "To view the log of the operation '{desc}', use the command 'yunohost log show {name}{name}'",
|
||||
|
@ -397,7 +410,7 @@
|
|||
"log_letsencrypt_cert_install": "Install a Let's Encrypt certificate on '{}' domain",
|
||||
"log_permission_create": "Create permission '{}'",
|
||||
"log_permission_delete": "Delete permission '{}'",
|
||||
"log_permission_url": "Update url related to permission '{}'",
|
||||
"log_permission_url": "Update URL related to permission '{}'",
|
||||
"log_selfsigned_cert_install": "Install self-signed certificate on '{}' domain",
|
||||
"log_letsencrypt_cert_renew": "Renew '{}' Let's Encrypt certificate",
|
||||
"log_regen_conf": "Regenerate system configurations '{}'",
|
||||
|
@ -466,6 +479,7 @@
|
|||
"migrations_to_be_ran_manually": "Migration {id} has to be run manually. Please go to Tools → Migrations on the webadmin page, or run `yunohost tools migrations run`.",
|
||||
"not_enough_disk_space": "Not enough free space on '{path}'",
|
||||
"invalid_number": "Must be a number",
|
||||
"invalid_password": "Invalid password",
|
||||
"operation_interrupted": "The operation was manually interrupted?",
|
||||
"packages_upgrade_failed": "Could not upgrade all the packages",
|
||||
"password_listed": "This password is among the most used passwords in the world. Please choose something more unique.",
|
||||
|
@ -549,7 +563,7 @@
|
|||
"service_already_started": "The service '{service}' is running already",
|
||||
"service_already_stopped": "The service '{service}' has already been stopped",
|
||||
"service_cmd_exec_failed": "Could not execute the command '{command}'",
|
||||
"service_description_avahi-daemon": "Allows you to reach your server using 'yunohost.local' in your local network",
|
||||
"service_description_yunomdns": "Allows you to reach your server using 'yunohost.local' in your local network",
|
||||
"service_description_dnsmasq": "Handles domain name resolution (DNS)",
|
||||
"service_description_dovecot": "Allows e-mail clients to access/fetch email (via IMAP and POP3)",
|
||||
"service_description_fail2ban": "Protects against brute-force and other kinds of attacks from the Internet",
|
||||
|
|
|
@ -332,7 +332,6 @@
|
|||
"hook_exec_failed": "Ne povis funkcii skripto: {path}",
|
||||
"global_settings_cant_open_settings": "Ne eblis malfermi agordojn, tial: {reason}",
|
||||
"user_created": "Uzanto kreita",
|
||||
"service_description_avahi-daemon": "Permesas al vi atingi vian servilon uzante 'yunohost.local' en via loka reto",
|
||||
"certmanager_attempt_to_replace_valid_cert": "Vi provas anstataŭigi bonan kaj validan atestilon por domajno {domain}! (Uzu --forte pretervidi)",
|
||||
"regenconf_updated": "Agordo ĝisdatigita por '{category}'",
|
||||
"update_apt_cache_warning": "Io iris malbone dum la ĝisdatigo de la kaŝmemoro de APT (paka administranto de Debian). Jen rubujo de la sources.list-linioj, kiuj povus helpi identigi problemajn liniojn:\n{sourceslist}",
|
||||
|
|
|
@ -238,7 +238,6 @@
|
|||
"service_description_fail2ban": "Protege contra ataques de fuerza bruta y otras clases de ataques desde Internet",
|
||||
"service_description_dovecot": "Permite a los clientes de correo acceder/obtener correo (vía IMAP y POP3)",
|
||||
"service_description_dnsmasq": "Maneja la resolución de nombres de dominio (DNS)",
|
||||
"service_description_avahi-daemon": "Permite acceder a su servidor usando «yunohost.local» en su red local",
|
||||
"server_reboot_confirm": "El servidor se reiniciará inmediatamente ¿está seguro? [{answers}]",
|
||||
"server_reboot": "El servidor se reiniciará",
|
||||
"server_shutdown_confirm": "El servidor se apagará inmediatamente ¿está seguro? [{answers}]",
|
||||
|
|
372
locales/fa.json
Normal file
372
locales/fa.json
Normal file
|
@ -0,0 +1,372 @@
|
|||
{
|
||||
"action_invalid": "اقدام نامعتبر '{action}'",
|
||||
"aborting": "رها کردن.",
|
||||
"app_change_url_failed_nginx_reload": "NGINX بارگیری نشد. در اینجا خروجی 'nginx -t' است:\n{nginx_errors}",
|
||||
"app_argument_required": "استدلال '{name}' الزامی است",
|
||||
"app_argument_password_no_default": "خطا هنگام تجزیه گذرواژه '{name}': به دلایل امنیتی استدلال رمز عبور نمی تواند مقدار پیش فرض داشته باشد",
|
||||
"app_argument_invalid": "یک مقدار معتبر انتخاب کنید برای استدلال '{name}':{error}",
|
||||
"app_argument_choice_invalid": "برای آرگومان '{name}' از یکی از این گزینه ها '{choices}' استفاده کنید",
|
||||
"app_already_up_to_date": "{app} در حال حاضر به روز است",
|
||||
"app_already_installed_cant_change_url": "این برنامه قبلاً نصب شده است. URL فقط با این عملکرد قابل تغییر نیست. در صورت موجود بودن برنامه `app changeurl` را بررسی کنید.",
|
||||
"app_already_installed": "{app} قبلاً نصب شده است",
|
||||
"app_action_broke_system": "این اقدام به نظر می رسد سرویس های مهمی را خراب کرده است: {services}",
|
||||
"app_action_cannot_be_ran_because_required_services_down": "برای اجرای این عملیات سرویس هایی که مورد نیازاند و باید اجرا شوند: {services}. سعی کنید آنها را مجدداً راه اندازی کنید (و علت خرابی احتمالی آنها را بررسی کنید).",
|
||||
"already_up_to_date": "کاری برای انجام دادن نیست. همه چیز در حال حاضر به روز است.",
|
||||
"admin_password_too_long": "لطفاً گذرواژه ای کوتاهتر از 127 کاراکتر انتخاب کنید",
|
||||
"admin_password_changed": "رمز مدیریت تغییر کرد",
|
||||
"admin_password_change_failed": "تغییر رمز امکان پذیر نیست",
|
||||
"admin_password": "رمز عبور مدیریت",
|
||||
"additional_urls_already_removed": "نشانی اینترنتی اضافی '{url}' قبلاً در نشانی اینترنتی اضافی برای اجازه '{permission}'حذف شده است",
|
||||
"additional_urls_already_added": "نشانی اینترنتی اضافی '{url}' قبلاً در نشانی اینترنتی اضافی برای اجازه '{permission}' اضافه شده است",
|
||||
"diagnosis_diskusage_low": "ذخیره سازی <code>{mountpoint}</code> (روی دستگاه <code>{device}</code>) فقط {free} ({free_percent}%) فضا باقی مانده(از {total}). مراقب باشید.",
|
||||
"diagnosis_diskusage_verylow": "ذخیره سازی <code>{mountpoint}</code> (روی دستگاه <code>{device}</code>) فقط {free} ({free_percent}%) فضا باقی مانده (از {total}). شما واقعاً باید پاکسازی فضای ذخیره ساز را در نظر بگیرید!",
|
||||
"diagnosis_services_bad_status_tip": "می توانید سعی کنید <a href='#/services/{service}'>سرویس را راه اندازی مجدد کنید</a>، و اگر کار نمی کند ، نگاهی داشته باشید به<a href='#/services/{service}'>سرویس در webadmin ثبت می شود</a> (از خط فرمان ، می توانید این کار را انجام دهید با <cmd>yunohost service restart {service}</cmd> و <cmd>yunohost service log {service}</cmd>).",
|
||||
"diagnosis_services_bad_status": "سرویس {service} {status} است :(",
|
||||
"diagnosis_services_conf_broken": "پیکربندی سرویس {service} خراب است!",
|
||||
"diagnosis_services_running": "سرویس {service} در حال اجرا است!",
|
||||
"diagnosis_domain_expires_in": "{domain} در {days} روز منقضی می شود.",
|
||||
"diagnosis_domain_expiration_error": "برخی از دامنه ها به زودی منقضی می شوند!",
|
||||
"diagnosis_domain_expiration_warning": "برخی از دامنه ها به زودی منقضی می شوند!",
|
||||
"diagnosis_domain_expiration_success": "دامنه های شما ثبت شده است و به این زودی منقضی نمی شود.",
|
||||
"diagnosis_domain_expiration_not_found_details": "به نظر می رسد اطلاعات WHOIS برای دامنه {domain} حاوی اطلاعات مربوط به تاریخ انقضا نیست؟",
|
||||
"diagnosis_domain_not_found_details": "دامنه {domain} در پایگاه داده WHOIS وجود ندارد یا منقضی شده است!",
|
||||
"diagnosis_domain_expiration_not_found": "بررسی تاریخ انقضا برخی از دامنه ها امکان پذیر نیست",
|
||||
"diagnosis_dns_specialusedomain": "دامنه {domain} بر اساس یک دامنه سطح بالا (TLD) مخصوص استفاده است و بنابراین انتظار نمی رود که دارای سوابق DNS واقعی باشد.",
|
||||
"diagnosis_dns_try_dyndns_update_force": "پیکربندی DNS این دامنه باید به طور خودکار توسط YunoHost مدیریت شود. اگر اینطور نیست ، می توانید سعی کنید به زور یک به روز رسانی را با استفاده از <cmd>yunohost dyndns update --force</cmd>.",
|
||||
"diagnosis_dns_point_to_doc": "لطفاً اسناد را در <a href='https://yunohost.org/dns_config'>https://yunohost.org/dns_config</a> برسی و مطالعه کنید، اگر در مورد پیکربندی سوابق DNS به کمک نیاز دارید.",
|
||||
"diagnosis_dns_discrepancy": "به نظر می رسد پرونده DNS زیر از پیکربندی توصیه شده پیروی نمی کند:<br>نوع: <code>{type}</code><br>نام: <code>{name}</code><br>ارزش فعلی: <code>{current}</code><br>مقدار مورد انتظار: <code>{value}</code>",
|
||||
"diagnosis_dns_missing_record": "با توجه به پیکربندی DNS توصیه شده ، باید یک رکورد DNS با اطلاعات زیر اضافه کنید.<br>نوع: <code>{type}</code><br> نام: <code>{name}</code><br>ارزش: <code>{value}</code>",
|
||||
"diagnosis_dns_bad_conf": "برخی از سوابق DNS برای دامنه {domain} (دسته {category}) وجود ندارد یا نادرست است",
|
||||
"diagnosis_dns_good_conf": "سوابق DNS برای دامنه {domain} (دسته {category}) به درستی پیکربندی شده است",
|
||||
"diagnosis_ip_weird_resolvconf_details": "پرونده <code>/etc/resolv.conf</code> باید یک پیوند همراه برای <code>/etc/resolvconf/run/resolv.conf</code> خود اشاره می کند به <code>127.0.0.1</code> (dnsmasq). اگر می خواهید راه حل های DNS را به صورت دستی پیکربندی کنید ، لطفاً ویرایش کنید <code>/etc/resolv.dnsmasq.conf</code>.",
|
||||
"diagnosis_ip_weird_resolvconf": "اینطور که پیداست تفکیک پذیری DNS کار می کند ، اما به نظر می رسد از سفارشی استفاده می کنید <code>/etc/resolv.conf</code>.",
|
||||
"diagnosis_ip_broken_resolvconf": "به نظر می رسد تفکیک پذیری نام دامنه در سرور شما شکسته شده است ، که به نظر می رسد مربوط به <code>/etc/resolv.conf</code> و اشاره نکردن به <code>127.0.0.1</code> میباشد.",
|
||||
"diagnosis_ip_broken_dnsresolution": "به نظر می رسد تفکیک پذیری نام دامنه به دلایلی خراب شده است... آیا فایروال درخواست های DNS را مسدود می کند؟",
|
||||
"diagnosis_ip_dnsresolution_working": "تفکیک پذیری نام دامنه کار می کند!",
|
||||
"diagnosis_ip_not_connected_at_all": "به نظر می رسد سرور اصلا به اینترنت متصل نیست !؟",
|
||||
"diagnosis_ip_local": "IP محلی: <code>{local}</code>",
|
||||
"diagnosis_ip_global": "IP جهانی: <code>{global}</code>",
|
||||
"diagnosis_ip_no_ipv6_tip": "داشتن یک IPv6 فعال برای کار سرور شما اجباری نیست ، اما برای سلامت اینترنت به طور کلی بهتر است. IPv6 معمولاً باید در صورت موجود بودن توسط سیستم یا ارائه دهنده اینترنت شما به طور خودکار پیکربندی شود. در غیر این صورت ، ممکن است لازم باشد چند مورد را به صورت دستی پیکربندی کنید ، همانطور که در اسناد اینجا توضیح داده شده است: <a href='https://yunohost.org/#/ipv6'>https://yunohost.org/#/ipv6</a>.اگر نمی توانید IPv6 را فعال کنید یا اگر برای شما بسیار فنی به نظر می رسد ، می توانید با خیال راحت این هشدار را نادیده بگیرید.",
|
||||
"diagnosis_ip_no_ipv6": "سرور IPv6 کار نمی کند.",
|
||||
"diagnosis_ip_connected_ipv6": "سرور از طریق IPv6 به اینترنت متصل است!",
|
||||
"diagnosis_ip_no_ipv4": "سرور IPv4 کار نمی کند.",
|
||||
"diagnosis_ip_connected_ipv4": "سرور از طریق IPv4 به اینترنت متصل است!",
|
||||
"diagnosis_no_cache": "هنوز هیچ حافظه نهانی معاینه و عیب یابی برای دسته '{category}' وجود ندارد",
|
||||
"diagnosis_failed": "نتیجه معاینه و عیب یابی برای دسته '{category}' واکشی نشد: {error}",
|
||||
"diagnosis_everything_ok": "همه چیز برای {category} خوب به نظر می رسد!",
|
||||
"diagnosis_found_warnings": "مورد (های) {warnings} یافت شده که می تواند دسته {category} را بهبود بخشد.",
|
||||
"diagnosis_found_errors_and_warnings": "{errors} مسائل مهم (و {warnings} هشدارها) مربوط به {category} پیدا شد!",
|
||||
"diagnosis_found_errors": "{errors} مشکلات مهم مربوط به {category} پیدا شد!",
|
||||
"diagnosis_ignored_issues": "(+ {nb_ignored} مسئله (ها) نادیده گرفته شده)",
|
||||
"diagnosis_cant_run_because_of_dep": "در حالی که مشکلات مهمی در ارتباط با {dep} وجود دارد ، نمی توان عیب یابی را برای {category} اجرا کرد.",
|
||||
"diagnosis_cache_still_valid": "(حافظه پنهان هنوز برای عیب یابی {category} معتبر است. هنوز دوباره تشخیص داده نمی شود!)",
|
||||
"diagnosis_failed_for_category": "عیب یابی برای دسته '{category}' ناموفق بود: {error}",
|
||||
"diagnosis_display_tip": "برای مشاهده مسائل پیدا شده ، می توانید به بخش تشخیص webadmin بروید یا از خط فرمان 'yunohost diagnosis show --issues --human-readable' را اجرا کنید.",
|
||||
"diagnosis_package_installed_from_sury_details": "برخی از بسته ها ناخواسته از مخزن شخص ثالث به نام Sury نصب شده اند. تیم YunoHost استراتژی مدیریت این بسته ها را بهبود بخشیده ، اما انتظار می رود برخی از تنظیماتی که برنامه های PHP7.3 را در حالی که هنوز بر روی Stretch نصب شده اند نصب کرده اند ، ناسازگاری های باقی مانده ای داشته باشند. برای رفع این وضعیت ، باید دستور زیر را اجرا کنید: <cmd>{cmd_to_fix}</cmd>",
|
||||
"diagnosis_package_installed_from_sury": "برخی از بسته های سیستمی باید کاهش یابد",
|
||||
"diagnosis_backports_in_sources_list": "به نظر می رسد apt (مدیریت بسته) برای استفاده از مخزن پشتیبان پیکربندی شده است. مگر اینکه واقعاً بدانید چه کار می کنید ، ما به شدت از نصب بسته های پشتیبان خودداری می کنیم، زیرا به احتمال زیاد باعث ایجاد ناپایداری یا تداخل در سیستم شما می شود.",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "شما نسخه های ناسازگار از بسته های YunoHost را اجرا می کنید... به احتمال زیاد به دلیل ارتقاء ناموفق یا جزئی است.",
|
||||
"diagnosis_basesystem_ynh_main_version": "سرور نسخه YunoHost {main_version} ({repo}) را اجرا می کند",
|
||||
"diagnosis_basesystem_ynh_single_version": "{package} نسخه: {version} ({repo})",
|
||||
"diagnosis_basesystem_kernel": "سرور نسخه {kernel_version} هسته لینوکس را اجرا می کند",
|
||||
"diagnosis_basesystem_host": "سرور نسخه {debian_version} دبیان را اجرا می کند",
|
||||
"diagnosis_basesystem_hardware_model": "مدل سرور {model} میباشد",
|
||||
"diagnosis_basesystem_hardware": "معماری سخت افزاری سرور {virt} {arch} است",
|
||||
"custom_app_url_required": "برای ارتقاء سفارشی برنامه {app} خود باید نشانی اینترنتی ارائه دهید",
|
||||
"confirm_app_install_thirdparty": "خطرناک! این برنامه بخشی از فهرست برنامه YunoHost نیست. نصب برنامه های شخص ثالث ممکن است یکپارچگی و امنیت سیستم شما را به خطر بیندازد. احتمالاً نباید آن را نصب کنید مگر اینکه بدانید در حال انجام چه کاری هستید. اگر این برنامه کار نکرد یا سیستم شما را خراب کرد ، هیچ پشتیبانی ارائه نخواهدشد... به هر حال اگر مایل به پذیرش این خطر هستید ، '{answers}' را تایپ کنید",
|
||||
"confirm_app_install_danger": "خطرناک! این برنامه هنوز آزمایشی است (اگر صراحتاً کار نکند)! احتمالاً نباید آن را نصب کنید مگر اینکه بدانید در حال انجام چه کاری هستید. اگر این برنامه کار نکرد یا سیستم شما را خراب کرد، هیچ پشتیبانی ارائه نخواهد شد... اگر به هر حال مایل به پذیرش این خطر هستید ، '{answers}' را تایپ کنید",
|
||||
"confirm_app_install_warning": "هشدار: این برنامه ممکن است کار کند ، اما در YunoHost یکپارچه نشده است. برخی از ویژگی ها مانند ورود به سیستم و پشتیبان گیری/بازیابی ممکن است در دسترس نباشد. به هر حال نصب شود؟ [{answers}] ",
|
||||
"certmanager_unable_to_parse_self_CA_name": "نتوانست نام مرجع خودامضائی را تجزیه و تحلیل کند (فایل: {file})",
|
||||
"certmanager_self_ca_conf_file_not_found": "فایل پیکربندی برای اجازه خود امضائی پیدا نشد (فایل: {file})",
|
||||
"certmanager_no_cert_file": "فایل گواهینامه برای دامنه {domain} خوانده نشد (فایل: {file})",
|
||||
"certmanager_hit_rate_limit": "اخیراً تعداد زیادی گواهی برای این مجموعه دقیق از دامنه ها {domain} صادر شده است. لطفاً بعداً دوباره امتحان کنید. برای جزئیات بیشتر به https://letsencrypt.org/docs/rate-limits/ مراجعه کنید",
|
||||
"certmanager_warning_subdomain_dns_record": "آدرس زیر دامنه '{subdomain}' به آدرس IP مشابه '{domain}' تبدیل نمی شود. تا زمانی که این مشکل را برطرف نکنید و گواهی را دوباره ایجاد نکنید ، برخی از ویژگی ها در دسترس نخواهند بود.",
|
||||
"certmanager_domain_http_not_working": "به نظر می رسد دامنه {domain} از طریق HTTP قابل دسترسی نیست. لطفاً برای اطلاعات بیشتر ، دسته \"وب\" را در عیب یابی بررسی کنید. (اگر می دانید چه کار می کنید ، از '--no-checks' برای خاموش کردن این چک ها استفاده کنید.)",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "سوابق DNS برای دامنه '{domain}' با IP این سرور متفاوت است. لطفاً برای اطلاعات بیشتر ، دسته 'DNS records' (پایه) را در عیب یابی بررسی کنید. اگر اخیراً رکورد A خود را تغییر داده اید ، لطفاً منتظر انتشار آن باشید (برخی از چکرهای انتشار DNS بصورت آنلاین در دسترس هستند). (اگر می دانید چه کار می کنید ، از '--no-checks' برای خاموش کردن این چک ها استفاده کنید.)",
|
||||
"certmanager_domain_cert_not_selfsigned": "گواهی دامنه {domain} خود امضا نشده است. آیا مطمئن هستید که می خواهید آن را جایگزین کنید؟ (برای این کار از '--force' استفاده کنید.)",
|
||||
"certmanager_domain_not_diagnosed_yet": "هنوز هیچ نتیجه تشخیصی و عیب یابی دامنه {domain} وجود ندارد. لطفاً در بخش عیب یابی ، دسته های 'DNS records' و 'Web'مجدداً عیب یابی را اجرا کنید تا بررسی شود که آیا دامنه ای برای گواهی اجازه رمزنگاری آماده است. (یا اگر می دانید چه کار می کنید ، از '--no-checks' برای خاموش کردن این بررسی ها استفاده کنید.)",
|
||||
"certmanager_certificate_fetching_or_enabling_failed": "تلاش برای استفاده از گواهینامه جدید برای {domain} جواب نداد...",
|
||||
"certmanager_cert_signing_failed": "گواهی جدید امضا نشده است",
|
||||
"certmanager_cert_renew_success": "گواهی اجازه رمزنگاری برای دامنه '{domain}' تمدید شد",
|
||||
"certmanager_cert_install_success_selfsigned": "گواهی خود امضا شده اکنون برای دامنه '{domain}' نصب شده است",
|
||||
"certmanager_cert_install_success": "هم اینک گواهی اجازه رمزگذاری برای دامنه '{domain}' نصب شده است",
|
||||
"certmanager_cannot_read_cert": "هنگام باز کردن گواهینامه فعلی مشکلی پیش آمده است برای دامنه {domain} (فایل: {file}) ، علّت: {reason}",
|
||||
"certmanager_attempt_to_replace_valid_cert": "شما در حال تلاش برای بازنویسی یک گواهی خوب و معتبر برای دامنه {domain} هستید! (استفاده از --force برای bypass)",
|
||||
"certmanager_attempt_to_renew_valid_cert": "گواهی دامنه '{domain}' در حال انقضا نیست! (اگر می دانید چه کار می کنید می توانید از --force استفاده کنید)",
|
||||
"certmanager_attempt_to_renew_nonLE_cert": "گواهی دامنه '{domain}' توسط Let's Encrypt صادر نشده است. به طور خودکار تمدید نمی شود!",
|
||||
"certmanager_acme_not_configured_for_domain": "در حال حاضر نمی توان چالش ACME را برای {domain} اجرا کرد زیرا nginx conf آن فاقد قطعه کد مربوطه است... لطفاً مطمئن شوید که پیکربندی nginx شما به روز است با استفاده از دستور `yunohost tools regen-conf nginx --dry-run --with-diff`.",
|
||||
"backup_with_no_restore_script_for_app": "{app} فاقد اسکریپت بازگردانی است ، نمی توانید پشتیبان گیری این برنامه را به طور خودکار بازیابی کنید.",
|
||||
"backup_with_no_backup_script_for_app": "برنامه '{app}' فاقد اسکریپت پشتیبان است. نادیده گرفتن.",
|
||||
"backup_unable_to_organize_files": "نمی توان از روش سریع برای سازماندهی فایل ها در بایگانی استفاده کرد",
|
||||
"backup_system_part_failed": "از بخش سیستم '{part}' پشتیبان گیری نشد",
|
||||
"backup_running_hooks": "درحال اجرای قلاب پشتیبان گیری...",
|
||||
"backup_permission": "مجوز پشتیبان گیری برای {app}",
|
||||
"backup_output_symlink_dir_broken": "فهرست بایگانی شما '{path}' یک پیوند symlink خراب است. شاید فراموش کرده اید که مجدداً محل ذخیره سازی که به آن اشاره می کند را دوباره نصب یا وصل کنید.",
|
||||
"backup_output_directory_required": "شما باید یک پوشه خروجی برای نسخه پشتیبان تهیه کنید",
|
||||
"backup_output_directory_not_empty": "شما باید یک دایرکتوری خروجی خالی انتخاب کنید",
|
||||
"backup_output_directory_forbidden": "دایرکتوری خروجی دیگری را انتخاب کنید. پشتیبان گیری نمی تواند در /bin، /boot، /dev ، /etc ، /lib ، /root ، /run ، /sbin ، /sys ، /usr ، /var یا /home/yunohost.backup/archives ایجاد شود",
|
||||
"backup_nothings_done": "چیزی برای ذخیره کردن وجود ندارد",
|
||||
"backup_no_uncompress_archive_dir": "چنین فهرست بایگانی فشرده نشده ایی وجود ندارد",
|
||||
"backup_mount_archive_for_restore": "در حال آماده سازی بایگانی برای بازگردانی...",
|
||||
"backup_method_tar_finished": "بایگانی پشتیبان TAR ایجاد شد",
|
||||
"backup_method_custom_finished": "روش پشتیبان گیری سفارشی '{method}' به پایان رسید",
|
||||
"backup_method_copy_finished": "نسخه پشتیبان نهایی شد",
|
||||
"backup_hook_unknown": "قلاب پشتیبان '{hook}' ناشناخته است",
|
||||
"backup_deleted": "نسخه پشتیبان حذف شد",
|
||||
"backup_delete_error": "'{path}' حذف نشد",
|
||||
"backup_custom_mount_error": "روش پشتیبان گیری سفارشی نمی تواند از مرحله 'mount' عبور کند",
|
||||
"backup_custom_backup_error": "روش پشتیبان گیری سفارشی نمی تواند مرحله 'backup' را پشت سر بگذارد",
|
||||
"backup_csv_creation_failed": "فایل CSV مورد نیاز برای بازیابی ایجاد نشد",
|
||||
"backup_csv_addition_failed": "فایلهای پشتیبان به فایل CSV اضافه نشد",
|
||||
"backup_creation_failed": "نسخه پشتیبان بایگانی ایجاد نشد",
|
||||
"backup_create_size_estimation": "بایگانی حاوی حدود {size} داده است.",
|
||||
"backup_created": "نسخه پشتیبان ایجاد شد",
|
||||
"backup_couldnt_bind": "نمی توان {src} را به {dest} متصل کرد.",
|
||||
"backup_copying_to_organize_the_archive": "در حال کپی {size} مگابایت برای سازماندهی بایگانی",
|
||||
"backup_cleaning_failed": "پوشه موقت پشتیبان گیری پاکسازی نشد",
|
||||
"backup_cant_mount_uncompress_archive": "بایگانی فشرده سازی نشده را نمی توان به عنوان حفاظت از نوشتن مستقر کرد",
|
||||
"backup_ask_for_copying_if_needed": "آیا می خواهید پشتیبان گیری را با استفاده از {size} مگابایت به طور موقت انجام دهید؟ (این روش استفاده می شود زیرا برخی از پرونده ها با استفاده از روش کارآمدتری تهیه نمی شوند.)",
|
||||
"backup_archive_writing_error": "فایل های '{source}' (که در بایگانی '{dest}' نامگذاری شده اند) برای پشتیبان گیری به بایگانی فشرده '{archive}' اضافه نشد",
|
||||
"backup_archive_system_part_not_available": "بخش سیستم '{part}' در این نسخه پشتیبان در دسترس نیست",
|
||||
"backup_archive_corrupted": "به نظر می رسد بایگانی پشتیبان '{archive}' خراب است: {error}",
|
||||
"backup_archive_cant_retrieve_info_json": "اطلاعات مربوط به بایگانی '{archive}' بارگیری نشد... info.json بازیابی نمی شود (یا json معتبری نیست).",
|
||||
"backup_archive_open_failed": "بایگانی پشتیبان باز نشد",
|
||||
"backup_archive_name_unknown": "بایگانی پشتیبان محلی ناشناخته با نام '{name}'",
|
||||
"backup_archive_name_exists": "بایگانی پشتیبان با این نام در حال حاضر وجود دارد.",
|
||||
"backup_archive_broken_link": "دسترسی به بایگانی پشتیبان امکان پذیر نیست (پیوند خراب به {path})",
|
||||
"backup_archive_app_not_found": "در بایگانی پشتیبان {app} پیدا نشد",
|
||||
"backup_applying_method_tar": "ایجاد آرشیو پشتیبان TAR...",
|
||||
"backup_applying_method_custom": "فراخوانی روش پشتیبان گیری سفارشی '{method}'...",
|
||||
"backup_applying_method_copy": "در حال کپی تمام فایل ها برای پشتیبان گیری...",
|
||||
"backup_app_failed": "{app} پشتیبان گیری نشد",
|
||||
"backup_actually_backuping": "ایجاد آرشیو پشتیبان از پرونده های جمع آوری شده...",
|
||||
"backup_abstract_method": "این روش پشتیبان گیری هنوز اجرا نشده است",
|
||||
"ask_password": "رمز عبور",
|
||||
"ask_new_path": "مسیر جدید",
|
||||
"ask_new_domain": "دامنه جدید",
|
||||
"ask_new_admin_password": "رمز جدید مدیریت",
|
||||
"ask_main_domain": "دامنه اصلی",
|
||||
"ask_lastname": "نام خانوادگی",
|
||||
"ask_firstname": "نام کوچک",
|
||||
"ask_user_domain": "دامنه ای که برای آدرس ایمیل کاربر و حساب XMPP استفاده می شود",
|
||||
"apps_catalog_update_success": "کاتالوگ برنامه به روز شد!",
|
||||
"apps_catalog_obsolete_cache": "حافظه پنهان کاتالوگ برنامه خالی یا منسوخ شده است.",
|
||||
"apps_catalog_failed_to_download": "بارگیری کاتالوگ برنامه {apps_catalog} امکان پذیر نیست: {error}",
|
||||
"apps_catalog_updating": "در حال به روز رسانی کاتالوگ برنامه…",
|
||||
"apps_catalog_init_success": "سیستم کاتالوگ برنامه راه اندازی اولیه شد!",
|
||||
"apps_already_up_to_date": "همه برنامه ها در حال حاضر به روز هستند",
|
||||
"app_packaging_format_not_supported": "این برنامه قابل نصب نیست زیرا قالب بسته بندی آن توسط نسخه YunoHost شما پشتیبانی نمی شود. احتمالاً باید ارتقاء سیستم خود را در نظر بگیرید.",
|
||||
"app_upgraded": "{app} ارتقا یافت",
|
||||
"app_upgrade_some_app_failed": "برخی از برنامه ها را نمی توان ارتقا داد",
|
||||
"app_upgrade_script_failed": "خطایی در داخل اسکریپت ارتقاء برنامه رخ داده است",
|
||||
"app_upgrade_failed": "{app} ارتقاء نیافت: {error}",
|
||||
"app_upgrade_app_name": "در حال ارتقاء {app}...",
|
||||
"app_upgrade_several_apps": "برنامه های زیر ارتقا می یابند: {apps}",
|
||||
"app_unsupported_remote_type": "نوع راه دور پشتیبانی نشده برای برنامه استفاده می شود",
|
||||
"app_unknown": "برنامه ناشناخته",
|
||||
"app_start_restore": "درحال بازیابی {app}...",
|
||||
"app_start_backup": "در حال جمع آوری فایل ها برای پشتیبان گیری {app}...",
|
||||
"app_start_remove": "در حال حذف {app}...",
|
||||
"app_start_install": "در حال نصب {app}...",
|
||||
"app_sources_fetch_failed": "نمی توان فایل های منبع را واکشی کرد ، آیا URL درست است؟",
|
||||
"app_restore_script_failed": "خطایی در داخل اسکریپت بازیابی برنامه رخ داده است",
|
||||
"app_restore_failed": "{app} بازیابی نشد: {error}",
|
||||
"app_remove_after_failed_install": "حذف برنامه در پی شکست نصب...",
|
||||
"app_requirements_unmeet": "شرایط مورد نیاز برای {app} برآورده نمی شود ، بسته {pkgname} ({version}) باید {spec} باشد",
|
||||
"app_requirements_checking": "در حال بررسی بسته های مورد نیاز برای {app}...",
|
||||
"app_removed": "{app} حذف نصب شد",
|
||||
"app_not_properly_removed": "{app} به درستی حذف نشده است",
|
||||
"app_not_installed": "{app} در لیست برنامه های نصب شده یافت نشد: {all_apps}",
|
||||
"app_not_correctly_installed": "به نظر می رسد {app} به اشتباه نصب شده است",
|
||||
"app_not_upgraded": "برنامه '{failed_app}' ارتقا پیدا نکرد و در نتیجه ارتقا برنامه های زیر لغو شد: {apps}",
|
||||
"app_manifest_install_ask_is_public": "آیا این برنامه باید در معرض دید بازدیدکنندگان ناشناس قرار گیرد؟",
|
||||
"app_manifest_install_ask_admin": "برای این برنامه یک کاربر سرپرست انتخاب کنید",
|
||||
"app_manifest_install_ask_password": "گذرواژه مدیریتی را برای این برنامه انتخاب کنید",
|
||||
"app_manifest_install_ask_path": "مسیر URL (بعد از دامنه) را انتخاب کنید که این برنامه باید در آن نصب شود",
|
||||
"app_manifest_install_ask_domain": "دامنه ای را انتخاب کنید که این برنامه باید در آن نصب شود",
|
||||
"app_manifest_invalid": "مشکلی در مانیفست برنامه وجود دارد: {error}",
|
||||
"app_location_unavailable": "این نشانی وب یا در دسترس نیست یا با برنامه (هایی) که قبلاً نصب شده در تعارض است:\n{apps}",
|
||||
"app_label_deprecated": "این دستور منسوخ شده است! لطفاً برای مدیریت برچسب برنامه از فرمان جدید'yunohost به روز رسانی مجوز کاربر' استفاده کنید.",
|
||||
"app_make_default_location_already_used": "نمی توان '{app}' را برنامه پیش فرض در دامنه قرار داد ، '{domain}' قبلاً توسط '{other_app}' استفاده می شود",
|
||||
"app_install_script_failed": "خطایی در درون اسکریپت نصب برنامه رخ داده است",
|
||||
"app_install_failed": "نصب {app} امکان پذیر نیست: {error}",
|
||||
"app_install_files_invalid": "این فایل ها قابل نصب نیستند",
|
||||
"app_id_invalid": "شناسه برنامه نامعتبر است",
|
||||
"app_full_domain_unavailable": "متأسفیم ، این برنامه باید در دامنه خود نصب شود ، اما سایر برنامه ها قبلاً در دامنه '{domain}' نصب شده اند.شما به جای آن می توانید از یک زیر دامنه اختصاص داده شده به این برنامه استفاده کنید.",
|
||||
"app_extraction_failed": "فایل های نصبی استخراج نشد",
|
||||
"app_change_url_success": "{app} URL اکنون {domain} {path} است",
|
||||
"app_change_url_no_script": "برنامه '{app_name}' هنوز از تغییر URL پشتیبانی نمی کند. شاید باید آن را ارتقا دهید.",
|
||||
"app_change_url_identical_domains": "دامنه /url_path قدیمی و جدیدیکسان هستند ('{domain}{path}') ، کاری برای انجام دادن نیست.",
|
||||
"diagnosis_http_connection_error": "خطای اتصال: ارتباط با دامنه درخواست شده امکان پذیر نیست، به احتمال زیاد غیرقابل دسترسی است.",
|
||||
"diagnosis_http_timeout": "زمان تلاش برای تماس با سرور از خارج به پایان رسید. به نظر می رسد غیرقابل دسترسی است.<br>1. شایع ترین علت برای این مشکل ، پورت 80 است (و 443) <a href='https://yunohost.org/isp_box_config'>به درستی به سرور شما ارسال نمی شوند</a>.<br>2. همچنین باید مطمئن شوید که سرویس nginx در حال اجرا است<br>3. در تنظیمات پیچیده تر: مطمئن شوید که هیچ فایروال یا پروکسی معکوسی تداخل نداشته باشد.",
|
||||
"diagnosis_http_ok": "دامنه {domain} از طریق HTTP از خارج از شبکه محلی قابل دسترسی است.",
|
||||
"diagnosis_http_localdomain": "انتظار نمی رود که دامنه {domain} ، با TLD محلی. از خارج از شبکه محلی به آن دسترسی پیدا کند.",
|
||||
"diagnosis_http_could_not_diagnose_details": "خطا: {error}",
|
||||
"diagnosis_http_could_not_diagnose": "نمی توان تشخیص داد که در IPv{ipversion} دامنه ها از خارج قابل دسترسی هستند یا خیر.",
|
||||
"diagnosis_http_hairpinning_issue_details": "این احتمالاً به دلیل جعبه / روتر ISP شما است. در نتیجه ، افراد خارج از شبکه محلی شما می توانند به سرور شما مطابق انتظار دسترسی پیدا کنند ، اما افراد داخل شبکه محلی (احتمالاً مثل شما؟) هنگام استفاده از نام دامنه یا IP جهانی. ممکن است بتوانید وضعیت را بهبود بخشید با نگاهی به <a href='https://yunohost.org/dns_local_network'>https://yunohost.org/dns_local_network</a>",
|
||||
"diagnosis_http_hairpinning_issue": "به نظر می رسد در شبکه محلی شما hairpinning فعال نشده است.",
|
||||
"diagnosis_ports_forwarding_tip": "برای رفع این مشکل، به احتمال زیاد باید انتقال پورت را در روتر اینترنت خود پیکربندی کنید همانطور که شرح داده شده در <a href='https://yunohost.org/isp_box_config'>https://yunohost.org/isp_box_config</a>",
|
||||
"diagnosis_ports_needed_by": "افشای این پورت برای ویژگی های {category} (سرویس {service}) مورد نیاز است",
|
||||
"diagnosis_ports_ok": "پورت {port} از خارج قابل دسترسی است.",
|
||||
"diagnosis_ports_partially_unreachable": "پورت {port} از خارج در {failed}IPv قابل دسترسی نیست.",
|
||||
"diagnosis_ports_unreachable": "پورت {port} از خارج قابل دسترسی نیست.",
|
||||
"diagnosis_ports_could_not_diagnose_details": "خطا: {error}",
|
||||
"diagnosis_ports_could_not_diagnose": "نمی توان تشخیص داد پورت ها از خارج در IPv{ipversion} قابل دسترسی هستند یا خیر.",
|
||||
"diagnosis_description_regenconf": "تنظیمات سیستم",
|
||||
"diagnosis_description_mail": "ایمیل",
|
||||
"diagnosis_description_web": "وب",
|
||||
"diagnosis_description_ports": "ارائه پورت ها",
|
||||
"diagnosis_description_systemresources": "منابع سیستم",
|
||||
"diagnosis_description_services": "بررسی وضعیّت سرویس ها",
|
||||
"diagnosis_description_dnsrecords": "رکورد DNS",
|
||||
"diagnosis_description_ip": "اتصال به اینترنت",
|
||||
"diagnosis_description_basesystem": "سیستم پایه",
|
||||
"diagnosis_security_vulnerable_to_meltdown_details": "برای رفع این مشکل ، باید سیستم خود را ارتقا دهید و مجدداً راه اندازی کنید تا هسته لینوکس جدید بارگیری شود (یا در صورت عدم کارکرد با ارائه دهنده سرور خود تماس بگیرید). برای اطلاعات بیشتر به https://meltdownattack.com/ مراجعه کنید.",
|
||||
"diagnosis_security_vulnerable_to_meltdown": "به نظر می رسد شما در برابر آسیب پذیری امنیتی بحرانی Meltdown آسیب پذیر هستید",
|
||||
"diagnosis_rootfstotalspace_critical": "کل سیستم فایل فقط دارای {space} است که بسیار نگران کننده است! احتمالاً خیلی زود فضای دیسک شما تمام می شود! توصیه می شود حداقل 16 گیگابایت و بیشتر فضا برای سیستم فایل ریشه داشته باشید.",
|
||||
"diagnosis_rootfstotalspace_warning": "سیستم فایل ریشه در مجموع فقط {space} دارد. ممکن است اشکالی نداشته باشد ، اما مراقب باشید زیرا در نهایت ممکن است فضای دیسک شما به سرعت تمام شود... توصیه می شود حداقل 16 گیگابایت و بیشتر فضا برای سیستم فایل ریشه داشته باشید.",
|
||||
"diagnosis_regenconf_manually_modified_details": "اگر بدانید چه کار می کنید ، احتمالاً خوب است! YunoHost به روز رسانی خودکار این فایل را متوقف می کند... اما مراقب باشید که ارتقاء YunoHost می تواند شامل تغییرات مهم توصیه شده باشد. اگر می خواهید ، می توانید تفاوت ها را با <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> و تنظیم مجدد پیکربندی توصیه شده به زور با فرمان <cmd>yunohost tools regen-conf {category} --force</cmd>",
|
||||
"diagnosis_regenconf_manually_modified": "به نظر می رسد فایل پیکربندی <code>{file}</code> به صورت دستی اصلاح شده است.",
|
||||
"diagnosis_regenconf_allgood": "همه فایلهای پیکربندی مطابق با تنظیمات توصیه شده است!",
|
||||
"diagnosis_mail_queue_too_big": "تعداد زیادی ایمیل معلق در صف پست ({nb_pending} ایمیل)",
|
||||
"diagnosis_mail_queue_unavailable_details": "خطا: {error}",
|
||||
"diagnosis_mail_queue_unavailable": "نمی توان با تعدادی از ایمیل های معلق در صف مشورت کرد",
|
||||
"diagnosis_mail_queue_ok": "{nb_pending} ایمیل های معلق در صف های ایمیل",
|
||||
"diagnosis_mail_blacklist_website": "پس از شناسایی دلیل لیست شدن و رفع آن، با خیال راحت درخواست کنید IP یا دامنه شما حذف شود از {blacklist_website}",
|
||||
"diagnosis_mail_blacklist_reason": "دلیل لیست سیاه: {reason}",
|
||||
"diagnosis_mail_blacklist_listed_by": "IP یا دامنه شما <code>{item}</code>در لیست سیاه {blacklist_name} قرار دارد",
|
||||
"diagnosis_mail_blacklist_ok": "به نظر می رسد IP ها و دامنه های مورد استفاده این سرور در لیست سیاه قرار ندارند",
|
||||
"diagnosis_mail_fcrdns_different_from_ehlo_domain_details": "DNS معکوس فعلی: <code>{rdns_domain}</code><br>مقدار مورد انتظار: <code>{ehlo_domain}</code>",
|
||||
"diagnosis_mail_fcrdns_different_from_ehlo_domain": "DNS معکوس به درستی در IPv{ipversion} پیکربندی نشده است. ممکن است برخی از ایمیل ها تحویل داده نشوند یا به عنوان هرزنامه پرچم گذاری شوند.",
|
||||
"diagnosis_mail_fcrdns_nok_alternatives_6": "برخی از ارائه دهندگان به شما اجازه نمی دهند DNS معکوس خود را پیکربندی کنید (یا ممکن است ویژگی آنها شکسته شود...). اگر DNS معکوس شما به درستی برای IPv4 پیکربندی شده است، با استفاده از آن می توانید هنگام ارسال ایمیل، استفاده از IPv6 را غیرفعال کنید. <cmd>yunohost settings set smtp.allow_ipv6 -v off</cmd>. توجه: این راه حل آخری به این معنی است که شما نمی توانید از چند سرور IPv6 موجود ایمیل ارسال یا دریافت کنید.",
|
||||
"diagnosis_mail_fcrdns_nok_alternatives_4": "برخی از ارائه دهندگان به شما اجازه نمی دهند DNS معکوس خود را پیکربندی کنید (یا ممکن است ویژگی آنها شکسته شود...). اگر به همین دلیل مشکلاتی را تجربه می کنید ، راه حل های زیر را در نظر بگیرید:<b > - برخی از ISP ها جایگزین ارائه می دهند <a href='https://yunohost.org/#/email_configure_relay'>با استفاده از رله سرور ایمیل</a> اگرچه به این معنی است که رله می تواند از ترافیک ایمیل شما جاسوسی کند.<br>- یک جایگزین دوستدار حریم خصوصی استفاده از VPN * با IP عمومی اختصاصی * برای دور زدن این نوع محدودیت ها است. ببینید <a href='https://yunohost.org/#/vpn_advantage'>https://yunohost.org/#/vpn_advantage</a><br>- یا ممکن است <a href='https://yunohost.org/#/isp'>به ارائه دهنده دیگری بروید</a>",
|
||||
"diagnosis_mail_fcrdns_nok_details": "ابتدا باید DNS معکوس را پیکربندی کنید با <code>{ehlo_domain}</code> در رابط روتر اینترنت یا رابط ارائه دهنده میزبانی تان. (ممکن است برخی از ارائه دهندگان میزبانی از شما بخواهند که برای این کار تیکت پشتیبانی ارسال کنید).",
|
||||
"diagnosis_mail_fcrdns_dns_missing": "در IPv{ipversion} هیچ DNS معکوسی تعریف نشده است. ممکن است برخی از ایمیل ها تحویل داده نشوند یا به عنوان هرزنامه پرچم گذاری شوند.",
|
||||
"diagnosis_mail_fcrdns_ok": "DNS معکوس شما به درستی پیکربندی شده است!",
|
||||
"diagnosis_mail_ehlo_could_not_diagnose_details": "خطا: {error}",
|
||||
"diagnosis_mail_ehlo_could_not_diagnose": "نمی توان تشخیص داد که آیا سرور ایمیل postfix از خارج در IPv{ipversion} قابل دسترسی است یا خیر.",
|
||||
"diagnosis_mail_ehlo_wrong_details": "EHLO دریافت شده توسط تشخیص دهنده از راه دور در IPv{ipversion} با دامنه سرور شما متفاوت است.<br>EHLO دریافت شده: <code>{wrong_ehlo}</code><br>انتظار می رود: <code>{right_ehlo}</code><br>شایع ترین علت این مشکل ، پورت 25 است <a href='https://yunohost.org/isp_box_config'>به درستی به سرور شما ارسال نشده است</a>. از سوی دیگر اطمینان حاصل کنید که هیچ فایروال یا پروکسی معکوسی تداخل ایجاد نمی کند.",
|
||||
"diagnosis_mail_ehlo_wrong": "یک سرور ایمیل SMTP متفاوت در IPv{ipversion} پاسخ می دهد. سرور شما احتمالاً نمی تواند ایمیل دریافت کند.",
|
||||
"diagnosis_mail_ehlo_bad_answer_details": "ممکن است به دلیل پاسخ دادن دستگاه دیگری به جای سرور شما باشد.",
|
||||
"diagnosis_mail_ehlo_bad_answer": "یک سرویس غیر SMTP در پورت 25 در IPv{ipversion} پاسخ داد",
|
||||
"diagnosis_mail_ehlo_unreachable_details": "اتصال روی پورت 25 سرور شما در IPv{ipversion} باز نشد. به نظر می رسد غیرقابل دسترس است.<br>1. شایع ترین علت این مشکل ، پورت 25 است <a href='https://yunohost.org/isp_box_config'>به درستی به سرور شما ارسال نشده است</a>.<br>2. همچنین باید مطمئن شوید که سرویس postfix در حال اجرا است.<br>3. در تنظیمات پیچیده تر: مطمئن شوید که هیچ فایروال یا پروکسی معکوسی تداخل نداشته باشد.",
|
||||
"diagnosis_mail_ehlo_unreachable": "سرور ایمیل SMTP از خارج در IPv {ipversion} غیرقابل دسترسی است. قادر به دریافت ایمیل نخواهد بود.",
|
||||
"diagnosis_mail_ehlo_ok": "سرور ایمیل SMTP از خارج قابل دسترسی است و بنابراین می تواند ایمیل دریافت کند!",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn": "برخی از ارائه دهندگان به شما اجازه نمی دهند پورت خروجی 25 را رفع انسداد کنید زیرا به بی طرفی شبکه اهمیتی نمی دهند.<br> - برخی از آنها جایگزین را ارائه می دهند <a href='https://yunohost.org/#/email_configure_relay'>با استفاده از رله سرور ایمیل</a> اگرچه به این معنی است که رله می تواند از ترافیک ایمیل شما جاسوسی کند.<br> - یک جایگزین دوستدار حریم خصوصی استفاده از VPN * با IP عمومی اختصاصی * برای دور زدن این نوع محدودیت ها است. ببینید <a href='https://yunohost.org/#/vpn_advantage'>https://yunohost.org/#/vpn_advantage</a><br>- همچنین می توانید تغییر را در نظر بگیرید به <a href='https://yunohost.org/#/isp'>یک ارائه دهنده بی طرف خالص تر</a>",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_details": "ابتدا باید سعی کنید پورت خروجی 25 را در رابط اینترنت روتر یا رابط ارائه دهنده میزبانی خود باز کنید. (ممکن است برخی از ارائه دهندگان میزبانی از شما بخواهند که برای این کار تیکت پشتیبانی ارسال کنید).",
|
||||
"diagnosis_mail_outgoing_port_25_blocked": "سرور ایمیل SMTP نمی تواند به سرورهای دیگر ایمیل ارسال کند زیرا درگاه خروجی 25 در IPv {ipversion} مسدود شده است.",
|
||||
"diagnosis_mail_outgoing_port_25_ok": "سرور ایمیل SMTP قادر به ارسال ایمیل است (پورت خروجی 25 مسدود نشده است).",
|
||||
"diagnosis_swap_tip": "لطفاً مراقب و آگاه باشید، اگر سرور میزبانی swap را روی کارت SD یا حافظه SSD انجام دهد ، ممکن است طول عمر دستگاه را به شدت کاهش دهد.",
|
||||
"diagnosis_swap_ok": "سیستم {total} swap دارد!",
|
||||
"diagnosis_swap_notsomuch": "سیستم فقط {total} swap دارد. برای جلوگیری از شرایطی که حافظه سیستم شما تمام می شود ، باید حداقل {recommended} را در نظر بگیرید.",
|
||||
"diagnosis_swap_none": "این سیستم به هیچ وجه swap ندارد. برای جلوگیری از شرایطی که حافظه سیستم شما تمام می شود ، باید حداقل {recommended} swap را در نظر بگیرید.",
|
||||
"diagnosis_ram_ok": "این سیستم هنوز {available} ({available_percent}٪) حافظه در دسترس دارد از مجموع {total}.",
|
||||
"diagnosis_ram_low": "این سیستم فقط {available} ({available_percent}٪) حافظه در دسترس دارد! (از {total}). مراقب باشید.",
|
||||
"diagnosis_ram_verylow": "این سیستم فقط {available} ({available_percent}٪) حافظه در دسترس دارد! (از {total})",
|
||||
"diagnosis_diskusage_ok": "ذخیره سازی <code>{mountpoint}</code> (روی دستگاه <code>{device}</code>) هنوز {free} فضا در دسترس دارد ({free_percent}%) فضای باقی مانده (از {total})!",
|
||||
"diagnosis_http_nginx_conf_not_up_to_date": "به نظر می رسد که پیکربندی nginx این دامنه به صورت دستی تغییر کرده است و از تشخیص YunoHost در صورت دسترسی به HTTP جلوگیری می کند.",
|
||||
"diagnosis_http_partially_unreachable": "به نظر می رسد که دامنه {domain} از طریق HTTP از خارج از شبکه محلی در IPv{failed} غیرقابل دسترسی است، اگرچه در IPv{passed} کار می کند.",
|
||||
"diagnosis_http_unreachable": "به نظر می رسد دامنه {domain} از خارج از شبکه محلی از طریق HTTP قابل دسترسی نیست.",
|
||||
"diagnosis_http_bad_status_code": "به نظر می رسد دستگاه دیگری (شاید روتر اینترنتی شما) به جای سرور شما پاسخ داده است.<br>1. شایع ترین علت برای این مشکل ، پورت 80 است (و 443) <a href='https://yunohost.org/isp_box_config'>به درستی به سرور شما ارسال نمی شوند</a>.<br>2. در تنظیمات پیچیده تر: مطمئن شوید که هیچ فایروال یا پروکسی معکوسی تداخل نداشته باشد.",
|
||||
"disk_space_not_sufficient_update": "برای به روزرسانی این برنامه فضای دیسک کافی باقی نمانده است",
|
||||
"disk_space_not_sufficient_install": "فضای کافی برای نصب این برنامه در دیسک باقی نمانده است",
|
||||
"diagnosis_sshd_config_inconsistent_details": "لطفاً اجراکنید <cmd>yunohost settings set security.ssh.port -v YOUR_SSH_PORT</cmd> برای تعریف پورت SSH و بررسی کنید <cmd>yunohost tools regen-conf ssh --dry-run --with-diff</cmd> و <cmd>yunohost tools regen-conf ssh --force</cmd> برای تنظیم مجدد تنظیمات خود به توصیه YunoHost.",
|
||||
"diagnosis_sshd_config_inconsistent": "به نظر می رسد که پورت SSH به صورت دستی در/etc/ssh/sshd_config تغییر یافته است. از زمان YunoHost 4.2 ، یک تنظیم جهانی جدید 'security.ssh.port' برای جلوگیری از ویرایش دستی پیکربندی در دسترس است.",
|
||||
"diagnosis_sshd_config_insecure": "به نظر می رسد که پیکربندی SSH به صورت دستی تغییر یافته است و مطمئن نیست زیرا هیچ دستورالعمل 'AllowGroups' یا 'AllowUsers' برای محدود کردن دسترسی به کاربران مجاز ندارد.",
|
||||
"diagnosis_processes_killed_by_oom_reaper": "برخی از فرآیندها اخیراً توسط سیستم از بین رفته اند زیرا حافظه آن تمام شده است. این به طور معمول نشانه کمبود حافظه در سیستم یا فرآیندی است که حافظه زیادی را از بین می برد. خلاصه فرآیندهای کشته شده:\n{kills_summary}",
|
||||
"diagnosis_never_ran_yet": "به نظر می رسد این سرور به تازگی راه اندازی شده است و هنوز هیچ گزارش تشخیصی برای نمایش وجود ندارد. شما باید با اجرای یک عیب یابی و تشخیص کامل، از طریق رابط مدیریت تحت وب webadmin یا با استفاده از 'yunohost diagnosis run' از خط فرمان معاینه و تشخیص عیب یابی را شروع کنید.",
|
||||
"diagnosis_unknown_categories": "دسته های زیر ناشناخته است: {categories}",
|
||||
"diagnosis_http_nginx_conf_not_up_to_date_details": "برای برطرف کردن وضعیّت ، تفاوت را با استفاده از خط فرمان بررسی کنید<cmd>yunohost tools regen-conf nginx --dry-run --with-diff</cmd> و اگر خوب است ، تغییرات را اعمال کنید با استفاده از فرمان <cmd>yunohost tools regen-conf nginx --force</cmd>.",
|
||||
"domain_cannot_remove_main_add_new_one": "شما نمی توانید '{domain}' را حذف کنید زیرا دامنه اصلی و تنها دامنه شما است، ابتدا باید دامنه دیگری را با 'yunohost domain add <another-domain.com>' اضافه کنید، سپس با استفاده از 'yunohost domain main-domain -n <another-domain.com>' به عنوان دامنه اصلی تنظیم شده. و بعد از آن می توانید'{domain}' را حذف کنید با استفاده از'yunohost domain remove {domain}'.'",
|
||||
"domain_cannot_add_xmpp_upload": "شما نمی توانید دامنه هایی را که با \"xmpp-upload\" شروع می شوند اضافه کنید. این نوع نام مختص ویژگی بارگذاری XMPP است که در YunoHost یکپارچه شده است.",
|
||||
"domain_cannot_remove_main": "شما نمی توانید '{domain}' را حذف کنید زیرا دامنه اصلی است ، ابتدا باید با استفاده از 'yunohost domain main-domain -n <another-domain>' دامنه دیگری را به عنوان دامنه اصلی تعیین کنید. در اینجا لیست دامنه های کاندید وجود دارد: {other_domains}",
|
||||
"installation_complete": "نصب تکمیل شد",
|
||||
"hook_name_unknown": "نام قلاب ناشناخته '{name}'",
|
||||
"hook_list_by_invalid": "از این ویژگی نمی توان برای فهرست قلاب ها استفاده کرد",
|
||||
"hook_json_return_error": "بازگشت از قلاب {path} خوانده نشد. خطا: {msg}. محتوای خام: {raw_content}",
|
||||
"hook_exec_not_terminated": "اسکریپت به درستی به پایان نرسید: {path}",
|
||||
"hook_exec_failed": "اسکریپت اجرا نشد: {path}",
|
||||
"group_user_not_in_group": "کاربر {user} در گروه {group} نیست",
|
||||
"group_user_already_in_group": "کاربر {user} در حال حاضر در گروه {group} است",
|
||||
"group_update_failed": "گروه '{group}' به روز نشد: {error}",
|
||||
"group_updated": "گروه '{group}' به روز شد",
|
||||
"group_unknown": "گروه '{group}' ناشناخته است",
|
||||
"group_deletion_failed": "گروه '{group}' حذف نشد: {error}",
|
||||
"group_deleted": "گروه '{group}' حذف شد",
|
||||
"group_cannot_be_deleted": "گروه {group} را نمی توان به صورت دستی حذف کرد.",
|
||||
"group_cannot_edit_primary_group": "گروه '{group}' را نمی توان به صورت دستی ویرایش کرد. این گروه اصلی شامل تنها یک کاربر خاص است.",
|
||||
"group_cannot_edit_visitors": "ویرایش گروه 'visitors' بازدیدکنندگان به صورت دستی امکان پذیر نیست. این گروه ویژه، نمایانگر بازدیدکنندگان ناشناس است",
|
||||
"group_cannot_edit_all_users": "گروه 'all_users' را نمی توان به صورت دستی ویرایش کرد. این یک گروه ویژه است که شامل همه کاربران ثبت شده در YunoHost میباشد",
|
||||
"group_creation_failed": "گروه '{group}' ایجاد نشد: {error}",
|
||||
"group_created": "گروه '{group}' ایجاد شد",
|
||||
"group_already_exist_on_system_but_removing_it": "گروه {group} از قبل در گروه های سیستم وجود دارد ، اما YunoHost آن را حذف می کند...",
|
||||
"group_already_exist_on_system": "گروه {group} از قبل در گروه های سیستم وجود دارد",
|
||||
"group_already_exist": "گروه {group} از قبل وجود دارد",
|
||||
"good_practices_about_user_password": "گذرواژه باید حداقل 8 کاراکتر باشد - اگرچه استفاده از گذرواژه طولانی تر (به عنوان مثال عبارت عبور) و/یا استفاده از تنوع کاراکترها (بزرگ ، کوچک ، رقم و کاراکتر های خاص) تمرین خوبی است.",
|
||||
"good_practices_about_admin_password": "اکنون می خواهید گذرواژه جدیدی برای مدیریت تعریف کنید. گذرواژه باید حداقل 8 کاراکتر باشد - اگرچه استفاده از گذرواژه طولانی تر (به عنوان مثال عبارت عبور) و/یا استفاده از تنوع کاراکترها (بزرگ ، کوچک ، رقم و کاراکتر های خاص) تمرین خوبی است.",
|
||||
"global_settings_unknown_type": "وضعیت غیرمنتظره ، به نظر می رسد که تنظیمات {setting} دارای نوع {unknown_type} است اما از نوع پشتیبانی شده توسط سیستم نیست.",
|
||||
"global_settings_setting_backup_compress_tar_archives": "هنگام ایجاد پشتیبان جدید ، بایگانی های فشرده (.tar.gz) را به جای بایگانی های فشرده نشده (.tar) انتخاب کنید. N.B. : فعال کردن این گزینه به معنای ایجاد آرشیوهای پشتیبان سبک تر است ، اما روش پشتیبان گیری اولیه به طور قابل توجهی طولانی تر و سنگین تر بر روی CPU خواهد بود.",
|
||||
"global_settings_setting_security_experimental_enabled": "فعال کردن ویژگی های امنیتی آزمایشی (اگر نمی دانید در حال انجام چه کاری هستید این کار را انجام ندهید!)",
|
||||
"global_settings_setting_security_webadmin_allowlist": "آدرس های IP که مجاز به دسترسی مدیر وب هستند. جدا شده با ویرگول.",
|
||||
"global_settings_setting_security_webadmin_allowlist_enabled": "فقط به برخی از IP ها اجازه دسترسی به مدیریت وب را بدهید.",
|
||||
"global_settings_setting_smtp_relay_password": "رمز عبور میزبان رله SMTP",
|
||||
"global_settings_setting_smtp_relay_user": "حساب کاربری رله SMTP",
|
||||
"global_settings_setting_smtp_relay_port": "پورت رله SMTP",
|
||||
"global_settings_setting_smtp_relay_host": "میزبان رله SMTP برای ارسال نامه به جای این نمونه yunohost استفاده می شود. اگر در یکی از این شرایط قرار دارید مفید است: پورت 25 شما توسط ارائه دهنده ISP یا VPS شما مسدود شده است، شما یک IP مسکونی دارید که در DUHL ذکر شده است، نمی توانید DNS معکوس را پیکربندی کنید یا این سرور مستقیماً در اینترنت نمایش داده نمی شود و می خواهید از یکی دیگر برای ارسال ایمیل استفاده کنید.",
|
||||
"global_settings_setting_smtp_allow_ipv6": "اجازه دهید از IPv6 برای دریافت و ارسال نامه استفاده شود",
|
||||
"global_settings_setting_ssowat_panel_overlay_enabled": "همپوشانی پانل SSOwat را فعال کنید",
|
||||
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "اجازه دهید از کلید میزبان DSA (منسوخ شده) برای پیکربندی SH daemon استفاده شود",
|
||||
"global_settings_unknown_setting_from_settings_file": "کلید ناشناخته در تنظیمات: '{setting_key}'، آن را کنار گذاشته و در /etc/yunohost/settings-unknown.json ذخیره کنید",
|
||||
"global_settings_setting_security_ssh_port": "درگاه SSH",
|
||||
"global_settings_setting_security_postfix_compatibility": "سازگاری در مقابل مبادله امنیتی برای سرور Postfix. روی رمزها (و سایر جنبه های مرتبط با امنیت) تأثیر می گذارد",
|
||||
"global_settings_setting_security_ssh_compatibility": "سازگاری در مقابل مبادله امنیتی برای سرور SSH. روی رمزها (و سایر جنبه های مرتبط با امنیت) تأثیر می گذارد",
|
||||
"global_settings_setting_security_password_user_strength": "قدرت رمز عبور کاربر",
|
||||
"global_settings_setting_security_password_admin_strength": "قدرت رمز عبور مدیر",
|
||||
"global_settings_setting_security_nginx_compatibility": "سازگاری در مقابل مبادله امنیتی برای وب سرور NGINX. روی رمزها (و سایر جنبه های مرتبط با امنیت) تأثیر می گذارد",
|
||||
"global_settings_setting_pop3_enabled": "پروتکل POP3 را برای سرور ایمیل فعال کنید",
|
||||
"global_settings_reset_success": "تنظیمات قبلی اکنون در {path} پشتیبان گیری شده است",
|
||||
"global_settings_key_doesnt_exists": "کلید '{settings_key}' در تنظیمات جهانی وجود ندارد ، با اجرای 'لیست تنظیمات yunohost' می توانید همه کلیدهای موجود را مشاهده کنید",
|
||||
"global_settings_cant_write_settings": "فایل تنظیمات ذخیره نشد، به دلیل: {reason}",
|
||||
"global_settings_cant_serialize_settings": "سریال سازی داده های تنظیمات انجام نشد، به دلیل: {reason}",
|
||||
"global_settings_cant_open_settings": "فایل تنظیمات باز نشد ، به دلیل: {reason}",
|
||||
"global_settings_bad_type_for_setting": "نوع نادرست برای تنظیم {setting} ، دریافت شده {received_type}، مورد انتظار {expected_type}",
|
||||
"global_settings_bad_choice_for_enum": "انتخاب نادرست برای تنظیم {setting} ، '{choice}' دریافت شد ، اما گزینه های موجود عبارتند از: {available_choices}",
|
||||
"firewall_rules_cmd_failed": "برخی از دستورات قانون فایروال شکست خورده است. اطلاعات بیشتر در گزارش.",
|
||||
"firewall_reloaded": "فایروال بارگیری مجدد شد",
|
||||
"firewall_reload_failed": "بارگیری مجدد فایروال امکان پذیر نیست",
|
||||
"file_does_not_exist": "فایل {path} وجود ندارد.",
|
||||
"field_invalid": "فیلد نامعتبر '{}'",
|
||||
"experimental_feature": "هشدار: این ویژگی آزمایشی است و پایدار تلقی نمی شود ، نباید از آن استفاده کنید مگر اینکه بدانید در حال انجام چه کاری هستید.",
|
||||
"extracting": "استخراج...",
|
||||
"dyndns_unavailable": "دامنه '{domain}' در دسترس نیست.",
|
||||
"dyndns_domain_not_provided": "ارائه دهنده DynDNS {provider} نمی تواند دامنه {domain} را ارائه دهد.",
|
||||
"dyndns_registration_failed": "دامنه DynDNS ثبت نشد: {error}",
|
||||
"dyndns_registered": "دامنه DynDNS ثبت شد",
|
||||
"dyndns_provider_unreachable": "دسترسی به ارائه دهنده DynDNS {provider} امکان پذیر نیست: یا YunoHost شما به درستی به اینترنت متصل نیست یا سرور dynette خراب است.",
|
||||
"dyndns_no_domain_registered": "هیچ دامنه ای با DynDNS ثبت نشده است",
|
||||
"dyndns_key_not_found": "کلید DNS برای دامنه یافت نشد",
|
||||
"dyndns_key_generating": "ایجاد کلید DNS... ممکن است مدتی طول بکشد.",
|
||||
"dyndns_ip_updated": "IP خود را در DynDNS به روز کرد",
|
||||
"dyndns_ip_update_failed": "آدرس IP را به DynDNS به روز نکرد",
|
||||
"dyndns_could_not_check_available": "بررسی نشد که آیا {domain} در {provider} در دسترس است یا خیر.",
|
||||
"dyndns_could_not_check_provide": "بررسی نشد که آیا {provider} می تواند {domain} را ارائه دهد یا خیر.",
|
||||
"dpkg_lock_not_available": "این دستور در حال حاضر قابل اجرا نیست زیرا به نظر می رسد برنامه دیگری از قفل dpkg (مدیر بسته سیستم) استفاده می کند",
|
||||
"dpkg_is_broken": "شما نمی توانید این کار را در حال حاضر انجام دهید زیرا dpkg/APT (اداره کنندگان سیستم بسته ها) به نظر می رسد در وضعیت خرابی است… می توانید با اتصال از طریق SSH و اجرا این فرمان `sudo apt install --fix-broken` and/or `sudo dpkg --configure -a` مشکل را حل کنید.",
|
||||
"downloading": "در حال بارگیری…",
|
||||
"done": "انجام شد",
|
||||
"domains_available": "دامنه های موجود:",
|
||||
"domain_unknown": "دامنه ناشناخته",
|
||||
"domain_name_unknown": "دامنه '{domain}' ناشناخته است",
|
||||
"domain_uninstall_app_first": "این برنامه ها هنوز روی دامنه شما نصب هستند:\n{apps}\n\nلطفاً قبل از اقدام به حذف دامنه ، آنها را با استفاده از 'برنامه yunohost remove the_app_id' حذف کرده یا با استفاده از 'yunohost app change-url the_app_id' به دامنه دیگری منتقل کنید",
|
||||
"domain_remove_confirm_apps_removal": "حذف این دامنه برنامه های زیر را حذف می کند:\n{apps}\n\nآیا طمئن هستید که میخواهید انجام دهید؟ [{answers}]",
|
||||
"domain_hostname_failed": "نام میزبان جدید قابل تنظیم نیست. این ممکن است بعداً مشکلی ایجاد کند (ممکن هم هست خوب باشد).",
|
||||
"domain_exists": "دامنه از قبل وجود دارد",
|
||||
"domain_dyndns_root_unknown": "دامنه ریشه DynDNS ناشناخته",
|
||||
"domain_dyndns_already_subscribed": "شما قبلاً در یک دامنه DynDNS مشترک شده اید",
|
||||
"domain_dns_conf_is_just_a_recommendation": "این دستور پیکربندی * توصیه شده * را به شما نشان می دهد. در واقع پیکربندی DNS را برای شما تنظیم نمی کند. این وظیفه شماست که مطابق این توصیه ، منطقه DNS خود را در ثبت کننده خود پیکربندی کنید.",
|
||||
"domain_deletion_failed": "حذف دامنه {domain} امکان پذیر نیست: {error}",
|
||||
"domain_deleted": "دامنه حذف شد",
|
||||
"domain_creation_failed": "ایجاد دامنه {domain} امکان پذیر نیست: {error}",
|
||||
"domain_created": "دامنه ایجاد شد",
|
||||
"domain_cert_gen_failed": "گواهی تولید نشد"
|
||||
}
|
|
@ -156,7 +156,7 @@
|
|||
"certmanager_attempt_to_renew_nonLE_cert": "Le certificat pour le domaine {domain} n’est pas émis par Let’s Encrypt. Impossible de le renouveler automatiquement !",
|
||||
"certmanager_attempt_to_renew_valid_cert": "Le certificat pour le domaine {domain} n’est pas sur le point d’expirer ! (Vous pouvez utiliser --force si vous savez ce que vous faites)",
|
||||
"certmanager_domain_http_not_working": "Le domaine {domain} ne semble pas être accessible via HTTP. Merci de vérifier la catégorie 'Web' dans le diagnostic pour plus d'informations. (Ou si vous savez ce que vous faites, utilisez '--no-checks' pour désactiver la vérification.)",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "L'enregistrement DNS du domaine '{domain}' est différent de l’adresse IP de ce serveur. Pour plus d'informations, veuillez consulter la catégorie \"Enregistrements DNS\" dans la section diagnostic. Si vous avez récemment modifié votre enregistrement A, veuillez attendre sa propagation (des vérificateurs de propagation DNS sont disponibles en ligne). (Si vous savez ce que vous faites, utilisez '--no-checks' pour désactiver ces contrôles)",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "Les enregistrements DNS du domaine '{domain}' sont différents de l’adresse IP de ce serveur. Pour plus d'informations, veuillez consulter la catégorie \"Enregistrements DNS\" dans la section diagnostic. Si vous avez récemment modifié votre enregistrement A, veuillez attendre sa propagation (des vérificateurs de propagation DNS sont disponibles en ligne). (Si vous savez ce que vous faites, utilisez '--no-checks' pour désactiver ces contrôles)",
|
||||
"certmanager_cannot_read_cert": "Quelque chose s’est mal passé lors de la tentative d’ouverture du certificat actuel pour le domaine {domain} (fichier : {file}), la cause est : {reason}",
|
||||
"certmanager_cert_install_success_selfsigned": "Le certificat auto-signé est maintenant installé pour le domaine « {domain} »",
|
||||
"certmanager_cert_install_success": "Le certificat Let’s Encrypt est maintenant installé pour le domaine « {domain} »",
|
||||
|
@ -217,10 +217,10 @@
|
|||
"backup_couldnt_bind": "Impossible de lier {src} avec {dest}.",
|
||||
"domain_dns_conf_is_just_a_recommendation": "Cette commande vous montre la configuration *recommandée*. Elle ne configure pas le DNS pour vous. Il est de votre ressort de configurer votre zone DNS chez votre registrar/fournisseur conformément à cette recommandation.",
|
||||
"migrations_cant_reach_migration_file": "Impossible d’accéder aux fichiers de migration via le chemin '%s'",
|
||||
"migrations_loading_migration": "Chargement de la migration {id}...",
|
||||
"migrations_loading_migration": "Chargement de la migration {id} ...",
|
||||
"migrations_migration_has_failed": "La migration {id} a échoué avec l’exception {exception} : annulation",
|
||||
"migrations_no_migrations_to_run": "Aucune migration à lancer",
|
||||
"migrations_skip_migration": "Ignorer et passer la migration {id}...",
|
||||
"migrations_skip_migration": "Ignorer et passer la migration {id} ...",
|
||||
"server_shutdown": "Le serveur va s’éteindre",
|
||||
"server_shutdown_confirm": "Le serveur va être éteint immédiatement, le voulez-vous vraiment ? [{answers}]",
|
||||
"server_reboot": "Le serveur va redémarrer",
|
||||
|
@ -234,7 +234,7 @@
|
|||
"migrations_list_conflict_pending_done": "Vous ne pouvez pas utiliser --previous et --done simultanément.",
|
||||
"migrations_to_be_ran_manually": "La migration {id} doit être lancée manuellement. Veuillez aller dans Outils > Migrations dans l’interface admin, ou lancer `yunohost tools migrations run`.",
|
||||
"migrations_need_to_accept_disclaimer": "Pour lancer la migration {id}, vous devez accepter cet avertissement :\n---\n{disclaimer}\n---\nSi vous acceptez de lancer la migration, veuillez relancer la commande avec l’option --accept-disclaimer.",
|
||||
"service_description_avahi-daemon": "Vous permet d’atteindre votre serveur en utilisant « yunohost.local » sur votre réseau local",
|
||||
"service_description_yunomdns": "Vous permet d’atteindre votre serveur en utilisant « yunohost.local » sur votre réseau local",
|
||||
"service_description_dnsmasq": "Gère la résolution des noms de domaine (DNS)",
|
||||
"service_description_dovecot": "Permet aux clients de messagerie d’accéder/récupérer les courriels (via IMAP et POP3)",
|
||||
"service_description_fail2ban": "Protège contre les attaques brute-force et autres types d’attaques venant d’Internet",
|
||||
|
@ -285,7 +285,7 @@
|
|||
"mail_unavailable": "Cette adresse de courriel est réservée et doit être automatiquement attribuée au tout premier utilisateur",
|
||||
"good_practices_about_admin_password": "Vous êtes sur le point de définir un nouveau mot de passe d'administration. Le mot de passe doit comporter au moins 8 caractères, bien qu'il soit recommandé d'utiliser un mot de passe plus long (c'est-à-dire une phrase secrète) et/ou d'utiliser une combinaison de caractères (majuscules, minuscules, chiffres et caractères spéciaux).",
|
||||
"good_practices_about_user_password": "Vous êtes sur le point de définir un nouveau mot de passe utilisateur. Le mot de passe doit comporter au moins 8 caractères, bien qu'il soit recommandé d'utiliser un mot de passe plus long (c'est-à-dire une phrase secrète) et/ou une combinaison de caractères (majuscules, minuscules, chiffres et caractères spéciaux).",
|
||||
"password_listed": "Ce mot de passe fait partie des mots de passe les plus utilisés dans le monde. Veuillez en choisir un autre moins commun et plus fort.",
|
||||
"password_listed": "Ce mot de passe fait partie des mots de passe les plus utilisés dans le monde. Veuillez en choisir un autre moins commun et plus robuste.",
|
||||
"password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères",
|
||||
"password_too_simple_2": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des majuscules et des minuscules",
|
||||
"password_too_simple_3": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des majuscules, des minuscules et des caractères spéciaux",
|
||||
|
@ -342,7 +342,7 @@
|
|||
"regenconf_would_be_updated": "La configuration aurait dû être mise à jour pour la catégorie '{category}'",
|
||||
"regenconf_dry_pending_applying": "Vérification de la configuration en attente qui aurait été appliquée pour la catégorie '{category}'…",
|
||||
"regenconf_failed": "Impossible de régénérer la configuration pour la ou les catégorie(s) : '{categories}'",
|
||||
"regenconf_pending_applying": "Applique la configuration en attente pour la catégorie '{category}'...",
|
||||
"regenconf_pending_applying": "Applique la configuration en attente pour la catégorie '{category}' ...",
|
||||
"service_regen_conf_is_deprecated": "'yunohost service regen-conf' est obsolète ! Veuillez plutôt utiliser 'yunohost tools regen-conf' à la place.",
|
||||
"tools_upgrade_at_least_one": "Veuillez spécifier '--apps' ou '--system'",
|
||||
"tools_upgrade_cant_both": "Impossible de mettre à niveau le système et les applications en même temps",
|
||||
|
@ -381,7 +381,7 @@
|
|||
"migrations_already_ran": "Ces migrations sont déjà effectuées : {ids}",
|
||||
"migrations_dependencies_not_satisfied": "Exécutez ces migrations : '{dependencies_id}', avant migration {id}.",
|
||||
"migrations_failed_to_load_migration": "Impossible de charger la migration {id} : {error}",
|
||||
"migrations_running_forward": "Exécution de la migration {id}...",
|
||||
"migrations_running_forward": "Exécution de la migration {id} ...",
|
||||
"migrations_success_forward": "Migration {id} terminée",
|
||||
"operation_interrupted": "L'opération a-t-elle été interrompue manuellement ?",
|
||||
"permission_already_exist": "L’autorisation '{permission}' existe déjà",
|
||||
|
@ -554,24 +554,24 @@
|
|||
"diagnosis_swap_tip": "Merci d'être prudent et conscient que si vous hébergez une partition SWAP sur une carte SD ou un disque SSD, cela risque de réduire drastiquement l’espérance de vie du périphérique.",
|
||||
"restore_already_installed_apps": "Les applications suivantes ne peuvent pas être restaurées car elles sont déjà installées : {apps}",
|
||||
"regenconf_need_to_explicitly_specify_ssh": "La configuration de ssh a été modifiée manuellement. Vous devez explicitement indiquer la mention --force à \"ssh\" pour appliquer les changements.",
|
||||
"migration_0015_cleaning_up": "Nettoyage du cache et des paquets qui ne sont plus nécessaires...",
|
||||
"migration_0015_specific_upgrade": "Démarrage de la mise à jour des paquets du système qui doivent être mis à jour séparément...",
|
||||
"migration_0015_cleaning_up": "Nettoyage du cache et des paquets qui ne sont plus nécessaires ...",
|
||||
"migration_0015_specific_upgrade": "Démarrage de la mise à jour des paquets du système qui doivent être mis à jour séparément ...",
|
||||
"migration_0015_modified_files": "Veuillez noter que les fichiers suivants ont été modifiés manuellement et pourraient être écrasés à la suite de la mise à niveau : {manually_modified_files}",
|
||||
"migration_0015_problematic_apps_warning": "Veuillez noter que des applications qui peuvent poser problèmes ont été détectées. Il semble qu'elles n'aient pas été installées à partir du catalogue d'applications YunoHost, ou bien qu'elles ne soient pas signalées comme \"fonctionnelles\". Par conséquent, il n'est pas possible de garantir que les applications suivantes fonctionneront encore après la mise à niveau : {problematic_apps}",
|
||||
"migration_0015_general_warning": "Veuillez noter que cette migration est une opération délicate. L'équipe YunoHost a fait de son mieux pour la revérifier et la tester, mais la migration pourrait quand même casser des éléments du système ou de ses applications.\n\nIl est donc recommandé :\n…- de faire une sauvegarde de toute donnée ou application critique. Plus d'informations ici https://yunohost.org/backup ;\n…- d'être patient après le lancement de la migration. Selon votre connexion internet et votre matériel, la mise à niveau peut prendre jusqu'à quelques heures.",
|
||||
"migration_0015_system_not_fully_up_to_date": "Votre système n'est pas entièrement à jour. Veuillez effectuer une mise à jour normale avant de lancer la migration vers Buster.",
|
||||
"migration_0015_not_enough_free_space": "L'espace libre est très faible dans /var/ ! Vous devriez avoir au moins 1 Go de libre pour effectuer cette migration.",
|
||||
"migration_0015_not_stretch": "La distribution Debian actuelle n'est pas Stretch !",
|
||||
"migration_0015_yunohost_upgrade": "Démarrage de la mise à jour de YunoHost...",
|
||||
"migration_0015_yunohost_upgrade": "Démarrage de la mise à jour de YunoHost ...",
|
||||
"migration_0015_still_on_stretch_after_main_upgrade": "Quelque chose s'est mal passé lors de la mise à niveau, le système semble toujours être sous Debian Stretch",
|
||||
"migration_0015_main_upgrade": "Démarrage de la mise à niveau générale...",
|
||||
"migration_0015_patching_sources_list": "Mise à jour du fichier sources.lists...",
|
||||
"migration_0015_main_upgrade": "Démarrage de la mise à niveau générale ...",
|
||||
"migration_0015_patching_sources_list": "Mise à jour du fichier sources.lists ...",
|
||||
"migration_0015_start": "Démarrage de la migration vers Buster",
|
||||
"migration_description_0015_migrate_to_buster": "Mise à niveau du système vers Debian Buster et YunoHost 4.x",
|
||||
"diagnosis_dns_try_dyndns_update_force": "La configuration DNS de ce domaine devrait être automatiquement gérée par YunoHost. Si ce n'est pas le cas, vous pouvez essayer de forcer une mise à jour en utilisant <cmd>yunohost dyndns update --force</cmd>.",
|
||||
"app_packaging_format_not_supported": "Cette application ne peut pas être installée car son format n'est pas pris en charge par votre version de YunoHost. Vous devriez probablement envisager de mettre à jour votre système.",
|
||||
"migration_0015_weak_certs": "Il a été constaté que les certificats suivants utilisent encore des algorithmes de signature peu robustes et doivent être mis à jour pour être compatibles avec la prochaine version de NGINX : {certs}",
|
||||
"global_settings_setting_backup_compress_tar_archives": "Compresser les archives (.tar.gz) au lieu de créer des archives non-compressées lors de la création des backups. N.B. Activer cette option permet de créer des archives plus légères, mais aussi d'avoir des procédures de backup significativement plus longues et plus gourmandes en CPU.",
|
||||
"global_settings_setting_backup_compress_tar_archives": "Lors de la création de nouvelles sauvegardes, compresser automatiquement les archives (.tar.gz) au lieu des archives non compressées (.tar). N.B. : activer cette option permet de créer des archives plus légères, mais la procédure de sauvegarde initiale sera significativement plus longues et plus gourmandes en CPU.",
|
||||
"migration_description_0018_xtable_to_nftable": "Migrer les anciennes règles de trafic réseau vers le nouveau système basé sur nftables",
|
||||
"service_description_php7.4-fpm": "Exécute les applications écrites en PHP avec NGINX",
|
||||
"migration_0018_failed_to_reset_legacy_rules": "La réinitialisation des règles iptable par défaut a échoué : {error}",
|
||||
|
@ -586,7 +586,7 @@
|
|||
"app_manifest_install_ask_is_public": "Cette application devrait-elle être visible par les visiteurs anonymes ?",
|
||||
"app_manifest_install_ask_admin": "Choisissez un administrateur pour cette application",
|
||||
"app_manifest_install_ask_password": "Choisissez un mot de passe administrateur pour cette application",
|
||||
"app_manifest_install_ask_path": "Choisissez le chemin sur lequel vous souhaitez installer cette application",
|
||||
"app_manifest_install_ask_path": "Choisissez le chemin d'URL (après le domaine) où cette application doit être installée",
|
||||
"app_manifest_install_ask_domain": "Choisissez le domaine sur lequel vous souhaitez installer cette application",
|
||||
"global_settings_setting_smtp_relay_user": "Compte utilisateur du relais SMTP",
|
||||
"global_settings_setting_smtp_relay_port": "Port du relais SMTP",
|
||||
|
@ -612,7 +612,7 @@
|
|||
"additional_urls_already_removed": "URL supplémentaire '{url}' déjà supprimées pour la permission '{permission}'",
|
||||
"invalid_number": "Doit être un nombre",
|
||||
"migration_description_0019_extend_permissions_features": "Étendre et retravailler le système de gestion des permissions applicatives",
|
||||
"diagnosis_basesystem_hardware_model": "Le modèle du serveur est {model}",
|
||||
"diagnosis_basesystem_hardware_model": "Le modèle/architecture du serveur est {model}",
|
||||
"diagnosis_backports_in_sources_list": "Il semble qu'apt (le gestionnaire de paquets) soit configuré pour utiliser le dépôt des rétroportages (backports). A moins que vous ne sachiez vraiment ce que vous faites, nous vous déconseillons fortement d'installer des paquets provenant des rétroportages, car cela risque de créer des instabilités ou des conflits sur votre système.",
|
||||
"postinstall_low_rootfsspace": "Le système de fichiers a une taille totale inférieure à 10 Go, ce qui est préoccupant et devrait attirer votre attention ! Vous allez certainement arriver à court d'espace disque (très) rapidement ! Il est recommandé d'avoir au moins 16 Go à la racine pour ce système de fichiers. Si vous voulez installer YunoHost malgré cet avertissement, relancez la post-installation avec --force-diskspace",
|
||||
"domain_remove_confirm_apps_removal": "Le retrait de ce domaine retirera aussi ces applications :\n{apps}\n\nÊtes vous sûr de vouloir cela ? [{answers}]",
|
||||
|
@ -633,5 +633,13 @@
|
|||
"diagnosis_sshd_config_inconsistent_details": "Veuillez exécuter <cmd>yunohost settings set security.ssh.port -v VOTRE_PORT_SSH</cmd> pour définir le port SSH, et vérifiez <cmd>yunohost tools regen-conf ssh --dry-run --with-diff</cmd> et <cmd>yunohost tools regen-conf ssh --force</cmd> pour réinitialiser votre configuration aux recommandations YunoHost.",
|
||||
"diagnosis_sshd_config_inconsistent": "Il semble que le port SSH a été modifié manuellement dans /etc/ssh/sshd_config. Depuis YunoHost 4.2, un nouveau paramètre global 'security.ssh.port' est disponible pour éviter de modifier manuellement la configuration.",
|
||||
"diagnosis_sshd_config_insecure": "La configuration SSH semble avoir été modifiée manuellement et n'est pas sécurisée car elle ne contient aucune directive 'AllowGroups' ou 'AllowUsers' pour limiter l'accès aux utilisateurs autorisés.",
|
||||
"backup_create_size_estimation": "L'archive contiendra environ {size} de données."
|
||||
"backup_create_size_estimation": "L'archive contiendra environ {size} de données.",
|
||||
"global_settings_setting_security_webadmin_allowlist": "Adresses IP autorisées à accéder à la page web du portail d'administration (webadmin). Elles doivent être séparées par une virgule.",
|
||||
"global_settings_setting_security_webadmin_allowlist_enabled": "Autorisez seulement certaines IP à accéder à la page web du portail d'administration (webadmin).",
|
||||
"diagnosis_http_localdomain": "Le domaine {domain}, avec un TLD .local, ne devrait pas être atteint depuis l'extérieur du réseau local.",
|
||||
"diagnosis_dns_specialusedomain": "Le domaine {domain} est basé sur un domaine de premier niveau (TLD) à usage spécial et ne devrait donc pas avoir d'enregistrements DNS réels.",
|
||||
"invalid_password": "Mot de passe incorrect",
|
||||
"ldap_server_is_down_restart_it": "Le service LDAP est en panne, essayez de le redémarrer...",
|
||||
"ldap_server_down": "Impossible d'atteindre le serveur LDAP",
|
||||
"global_settings_setting_security_experimental_enabled": "Activer les fonctionnalités de sécurité expérimentales (ne l'activez pas si vous ne savez pas ce que vous faites !)"
|
||||
}
|
302
locales/gl.json
302
locales/gl.json
|
@ -67,7 +67,7 @@
|
|||
"app_remove_after_failed_install": "Eliminando a app debido ao fallo na instalación...",
|
||||
"app_requirements_unmeet": "Non se cumpren os requerimentos de {app}, o paquete {pkgname} ({version}) debe ser {spec}",
|
||||
"app_requirements_checking": "Comprobando os paquetes requeridos por {app}...",
|
||||
"app_removed": "{app} eliminada",
|
||||
"app_removed": "{app} desinstalada",
|
||||
"app_not_properly_removed": "{app} non se eliminou de xeito correcto",
|
||||
"app_not_installed": "Non se puido atopar {app} na lista de apps instaladas: {all_apps}",
|
||||
"app_not_correctly_installed": "{app} semella que non está instalada correctamente",
|
||||
|
@ -75,7 +75,7 @@
|
|||
"app_manifest_install_ask_is_public": "Debería esta app estar exposta ante visitantes anónimas?",
|
||||
"app_manifest_install_ask_admin": "Elixe unha usuaria administradora para esta app",
|
||||
"app_manifest_install_ask_password": "Elixe un contrasinal de administración para esta app",
|
||||
"app_manifest_install_ask_path": "Elixe a ruta onde queres instalar esta app",
|
||||
"app_manifest_install_ask_path": "Elixe a ruta URL (após o dominio) onde será instalada esta app",
|
||||
"app_manifest_install_ask_domain": "Elixe o dominio onde queres instalar esta app",
|
||||
"app_manifest_invalid": "Hai algún erro no manifesto da app: {error}",
|
||||
"app_location_unavailable": "Este URL ou ben non está dispoñible ou entra en conflito cunha app(s) xa instalada:\n{apps}",
|
||||
|
@ -345,5 +345,301 @@
|
|||
"global_settings_setting_smtp_relay_password": "Contrasinal no repetidor SMTP",
|
||||
"global_settings_setting_smtp_relay_user": "Conta de usuaria no repetidor SMTP",
|
||||
"global_settings_setting_smtp_relay_port": "Porto do repetidor SMTP",
|
||||
"global_settings_setting_smtp_relay_host": "Servidor repetidor SMTP para enviar emails no lugar da túa instancia yunohost. É útil se estás nunha destas situacións: o teu porto 25 está bloqueado polo teu provedor ISP u VPN, se tes unha IP residencial nunha lista DUHL, se non podes configurar DNS inversa ou se este servidor non ten conexión directa a internet e queres utilizar outro para enviar os emails."
|
||||
"global_settings_setting_smtp_relay_host": "Servidor repetidor SMTP para enviar emails no lugar da túa instancia yunohost. É útil se estás nunha destas situacións: o teu porto 25 está bloqueado polo teu provedor ISP u VPN, se tes unha IP residencial nunha lista DUHL, se non podes configurar DNS inversa ou se este servidor non ten conexión directa a internet e queres utilizar outro para enviar os emails.",
|
||||
"group_updated": "Grupo '{group}' actualizado",
|
||||
"group_unknown": "Grupo descoñecido '{group}'",
|
||||
"group_deletion_failed": "Non se eliminou o grupo '{group}': {error}",
|
||||
"group_deleted": "Grupo '{group}' eliminado",
|
||||
"group_cannot_be_deleted": "O grupo {group} non se pode eliminar manualmente.",
|
||||
"group_cannot_edit_primary_group": "O grupo '{group}' non se pode editar manualmente. É o grupo primario que contén só a unha usuaria concreta.",
|
||||
"group_cannot_edit_visitors": "O grupo 'visitors' non se pode editar manualmente. É un grupo especial que representa a tódas visitantes anónimas",
|
||||
"group_cannot_edit_all_users": "O grupo 'all_users' non se pode editar manualmente. É un grupo especial que contén tódalas usuarias rexistradas en YunoHost",
|
||||
"global_settings_setting_security_webadmin_allowlist": "Enderezos IP con permiso para acceder á webadmin. Separados por vírgulas.",
|
||||
"global_settings_setting_security_webadmin_allowlist_enabled": "Permitir que só algúns IPs accedan á webadmin.",
|
||||
"disk_space_not_sufficient_update": "Non hai espazo suficiente no disco para actualizar esta aplicación",
|
||||
"disk_space_not_sufficient_install": "Non queda espazo suficiente no disco para instalar esta aplicación",
|
||||
"log_help_to_get_log": "Para ver o rexistro completo da operación '{desc}', usa o comando 'yunohost log show {name}{name}'",
|
||||
"log_link_to_log": "Rexistro completo desta operación: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>'",
|
||||
"log_corrupted_md_file": "O ficheiro YAML con metadatos asociado aos rexistros está danado: '{md_file}\nErro: {error}'",
|
||||
"iptables_unavailable": "Non podes andar remexendo en iptables aquí. Ou ben estás nun contedor ou o teu kernel non ten soporte para isto",
|
||||
"ip6tables_unavailable": "Non podes remexer en ip6tables aquí. Ou ben estás nun contedor ou o teu kernel non ten soporte para isto",
|
||||
"invalid_regex": "Regex non válido: '{regex}'",
|
||||
"installation_complete": "Instalación completa",
|
||||
"hook_name_unknown": "Nome descoñecido do gancho '{name}'",
|
||||
"hook_list_by_invalid": "Esta propiedade non se pode usar para enumerar os ganchos",
|
||||
"hook_json_return_error": "Non se puido ler a info de retorno do gancho {path}. Erro: {msg}. Contido en bruto: {raw_content}",
|
||||
"hook_exec_not_terminated": "O script non rematou correctamente: {path}",
|
||||
"hook_exec_failed": "Non se executou o script: {path}",
|
||||
"group_user_not_in_group": "A usuaria {user} non está no grupo {group}",
|
||||
"group_user_already_in_group": "A usuaria {user} xa está no grupo {group}",
|
||||
"group_update_failed": "Non se actualizou o grupo '{group}': {error}",
|
||||
"log_permission_delete": "Eliminar permiso '{}'",
|
||||
"log_permission_create": "Crear permiso '{}'",
|
||||
"log_letsencrypt_cert_install": "Instalar un certificado Let's Encrypt para o dominio '{}'",
|
||||
"log_dyndns_update": "Actualizar o IP asociado ao teu subdominio YunoHost '{}'",
|
||||
"log_dyndns_subscribe": "Subscribirse a un subdominio YunoHost '{}'",
|
||||
"log_domain_remove": "Eliminar o dominio '{}' da configuración do sistema",
|
||||
"log_domain_add": "Engadir dominio '{}' á configuración do sistema",
|
||||
"log_remove_on_failed_install": "Eliminar '{}' tras unha instalación fallida",
|
||||
"log_remove_on_failed_restore": "Eliminar '{}' tras un intento fallido de restablecemento desde copia",
|
||||
"log_backup_restore_app": "Restablecer '{}' desde unha copia de apoio",
|
||||
"log_backup_restore_system": "Restablecer o sistema desde unha copia de apoio",
|
||||
"log_backup_create": "Crear copia de apoio",
|
||||
"log_available_on_yunopaste": "Este rexistro está dispoñible en {url}",
|
||||
"log_app_config_apply": "Aplicar a configuración da app '{}'",
|
||||
"log_app_config_show_panel": "Mostrar o panel de configuración da app '{}'",
|
||||
"log_app_action_run": "Executar acción da app '{}'",
|
||||
"log_app_makedefault": "Converter '{}' na app por defecto",
|
||||
"log_app_upgrade": "Actualizar a app '{}'",
|
||||
"log_app_remove": "Eliminar a app '{}'",
|
||||
"log_app_install": "Instalar a app '{}'",
|
||||
"log_app_change_url": "Cambiar o URL da app '{}'",
|
||||
"log_operation_unit_unclosed_properly": "Non se pechou correctamente a unidade da operación",
|
||||
"log_does_exists": "Non hai rexistro de operación co nome '{log}', usa 'yunohost log list' para ver tódolos rexistros de operacións dispoñibles",
|
||||
"log_help_to_get_failed_log": "A operación '{desc}' non se completou. Comparte o rexistro completo da operación utilizando o comando 'yunohost log share {name}' para obter axuda",
|
||||
"log_link_to_failed_log": "Non se completou a operación '{desc}'. Por favor envía o rexistro completo desta operación <a href=\"#/tools/logs/{name}\">premendo aquí</a> para obter axuda",
|
||||
"migration_0015_start": "Comezando a migración a Buster",
|
||||
"migration_update_LDAP_schema": "Actualizando esquema LDAP...",
|
||||
"migration_ldap_rollback_success": "Sistema restablecido.",
|
||||
"migration_ldap_migration_failed_trying_to_rollback": "Non se puido migrar... intentando volver á versión anterior do sistema.",
|
||||
"migration_ldap_can_not_backup_before_migration": "O sistema de copia de apoio do sistema non se completou antes de que fallase a migración. Erro: {error}",
|
||||
"migration_ldap_backup_before_migration": "Crear copia de apoio da base de datos LDAP e axustes de apps antes de realizar a migración.",
|
||||
"migration_description_0020_ssh_sftp_permissions": "Engadir soporte para permisos SSH e SFTP",
|
||||
"migration_description_0019_extend_permissions_features": "Extender/recrear o sistema de xestión de permisos de apps",
|
||||
"migration_description_0018_xtable_to_nftable": "Migrar as regras de tráfico de rede antigas ao novo sistema nftable",
|
||||
"migration_description_0017_postgresql_9p6_to_11": "Migrar bases de datos desde PostgreSQL 9.6 a 11",
|
||||
"migration_description_0016_php70_to_php73_pools": "Migrar o ficheiros de configuración 'pool' de php7.0-fpm a php7.3",
|
||||
"migration_description_0015_migrate_to_buster": "Actualizar o sistema a Debian Buster e YunoHost 4.x",
|
||||
"migrating_legacy_permission_settings": "Migrando os axustes dos permisos anteriores...",
|
||||
"main_domain_changed": "Foi cambiado o dominio principal",
|
||||
"main_domain_change_failed": "Non se pode cambiar o dominio principal",
|
||||
"mail_unavailable": "Este enderezo de email está reservado e debería adxudicarse automáticamente á primeira usuaria",
|
||||
"mailbox_used_space_dovecot_down": "O servizo de caixa de correo Dovecot ten que estar activo se queres obter o espazo utilizado polo correo",
|
||||
"mailbox_disabled": "Desactivado email para usuaria {user}",
|
||||
"mail_forward_remove_failed": "Non se eliminou o reenvío de email '{mail}'",
|
||||
"mail_domain_unknown": "Enderezo de email non válido para o dominio '{domain}'. Usa un dominio administrado por este servidor.",
|
||||
"mail_alias_remove_failed": "Non se puido eliminar o alias de email '{mail}'",
|
||||
"log_tools_reboot": "Reiniciar o servidor",
|
||||
"log_tools_shutdown": "Apagar o servidor",
|
||||
"log_tools_upgrade": "Actualizar paquetes do sistema",
|
||||
"log_tools_postinstall": "Postinstalación do servidor YunoHost",
|
||||
"log_tools_migrations_migrate_forward": "Executar migracións",
|
||||
"log_domain_main_domain": "Facer que '{}' sexa o dominio principal",
|
||||
"log_user_permission_reset": "Restablecer permiso '{}'",
|
||||
"log_user_permission_update": "Actualizar accesos para permiso '{}'",
|
||||
"log_user_update": "Actualizar info da usuaria '{}'",
|
||||
"log_user_group_update": "Actualizar grupo '{}'",
|
||||
"log_user_group_delete": "Eliminar grupo '{}'",
|
||||
"log_user_group_create": "Crear grupo '{}'",
|
||||
"log_user_delete": "Eliminar usuaria '{}'",
|
||||
"log_user_create": "Engadir usuaria '{}'",
|
||||
"log_regen_conf": "Rexerar configuración do sistema '{}'",
|
||||
"log_letsencrypt_cert_renew": "Anovar certificado Let's Encrypt para '{}'",
|
||||
"log_selfsigned_cert_install": "Instalar certificado auto-asinado para o dominio '{}'",
|
||||
"log_permission_url": "Actualizar URL relativo ao permiso '{}'",
|
||||
"migration_0015_general_warning": "Ten en conta que a migración é unha operación delicada. O equipo YunoHost esforzouse revisando e comprobandoa, aínda así algo podería fallar en partes do teu sistema ou as súas apps.\n\nPor tanto, é recomendable:\n- realiza unha copia de apoio de tódolos datos ou apps importantes. Máis info en https://yunohost.org/backup;\n - ten paciencia tras iniciar o proceso: dependendo da túa conexión de internet e hardware podería demorar varias horas a actualización de tódolos compoñentes.",
|
||||
"migration_0015_system_not_fully_up_to_date": "O teu sistema non está ao día. Realiza unha actualización común antes de realizar a migración a Buster.",
|
||||
"migration_0015_not_enough_free_space": "Queda moi pouco espazo en /var/! Deberías ter polo menos 1GB libre para realizar a migración.",
|
||||
"migration_0015_not_stretch": "A distribución Debian actual non é Stretch!",
|
||||
"migration_0015_yunohost_upgrade": "Iniciando a actualización do núcleo YunoHost...",
|
||||
"migration_0015_still_on_stretch_after_main_upgrade": "Algo foi mal durante a actualiza ión principal, o sistema semella que aínda está en Debian Stretch",
|
||||
"migration_0015_main_upgrade": "Iniciando a actualización principal...",
|
||||
"migration_0015_patching_sources_list": "Correxindo os sources.lists...",
|
||||
"migrations_already_ran": "Xa se realizaron estas migracións: {ids}",
|
||||
"migration_0019_slapd_config_will_be_overwritten": "Semella que editaches manualmente a configuración slapd. Para esta migración crítica YunoHost precisa forzar a actualización da configuración slapd. Os ficheiros orixinais van ser copiados en {conf_backup_folder}.",
|
||||
"migration_0019_add_new_attributes_in_ldap": "Engadir novos atributos para os permisos na base de datos LDAP",
|
||||
"migration_0018_failed_to_reset_legacy_rules": "Fallou o restablecemento das regras antigas de iptables: {error}",
|
||||
"migration_0018_failed_to_migrate_iptables_rules": "Fallou a migración das regras antigas de iptables a nftables: {error}",
|
||||
"migration_0017_not_enough_space": "Crea espazo suficiente en {path} para executar a migración.",
|
||||
"migration_0017_postgresql_11_not_installed": "PostgreSQL 9.6 está instado, pero non postgresql 11? Algo raro debeu acontecer no teu sistema :(...",
|
||||
"migration_0017_postgresql_96_not_installed": "PostgreSQL non está instalado no teu sistema. Nada que facer.",
|
||||
"migration_0015_weak_certs": "Os seguintes certificados están a utilizar algoritmos de sinatura débiles e teñen que ser actualizados para ser compatibles coa seguinte versión de nginx: {certs}",
|
||||
"migration_0015_cleaning_up": "Limpando a caché e paquetes que xa non son útiles...",
|
||||
"migration_0015_specific_upgrade": "Iniciando a actualización dos paquetes do sistema que precisan ser actualizados de xeito independente...",
|
||||
"migration_0015_modified_files": "Ten en conta que os seguintes ficheiros semella que foron modificados manualmente e poderían ser sobrescritos na actualización: {manually_modified_files}",
|
||||
"migration_0015_problematic_apps_warning": "Ten en conta que se detectaron as seguintes apps que poderían ser problemáticas. Semella que non foron instaladas usando o catálogo de YunoHost, ou non están marcadas como 'funcionais'. En consecuencia, non se pode garantir que seguirán funcionando após a actualización: {problematic_apps}",
|
||||
"diagnosis_http_localdomain": "O dominio {domain}, cun TLD .local, non é de agardar que sexa accesible desde o exterior da rede local.",
|
||||
"diagnosis_dns_specialusedomain": "O dominio {domain} baséase un dominio de nivel alto e uso especial (TLD) polo que non é de agardar que realmente teña rexistros DNS.",
|
||||
"upnp_enabled": "UPnP activado",
|
||||
"upnp_disabled": "UPnP desactivado",
|
||||
"permission_creation_failed": "Non se creou o permiso '{permission}': {error}",
|
||||
"permission_created": "Creado o permiso '{permission}'",
|
||||
"permission_cannot_remove_main": "Non está permitido eliminar un permiso principal",
|
||||
"permission_already_up_to_date": "Non se actualizou o permiso porque as solicitudes de adición/retirada xa coinciden co estado actual.",
|
||||
"permission_already_exist": "Xa existe o permiso '{permission}'",
|
||||
"permission_already_disallowed": "O grupo '{group}' xa ten o permiso '{permission}' desactivado",
|
||||
"permission_already_allowed": "O grupo '{group}' xa ten o permiso '{permission}' activado",
|
||||
"pattern_password_app": "Lamentámolo, os contrasinais non poden conter os seguintes caracteres: {forbidden_chars}",
|
||||
"pattern_username": "Só admite caracteres alfanuméricos en minúscula e trazo baixo",
|
||||
"pattern_positive_number": "Ten que ser un número positivo",
|
||||
"pattern_port_or_range": "Debe ser un número válido de porto (entre 0-65535) ou rango de portos (ex. 100:200)",
|
||||
"pattern_password": "Ten que ter polo menos 3 caracteres",
|
||||
"pattern_mailbox_quota": "Ten que ser un tamaño co sufixo b/k/M/G/T ou 0 para non ter unha cota",
|
||||
"pattern_lastname": "Ten que ser un apelido válido",
|
||||
"pattern_firstname": "Ten que ser un nome válido",
|
||||
"pattern_email": "Ten que ser un enderezo de email válido, sen o símbolo '+' (ex. persoa@exemplo.com)",
|
||||
"pattern_email_forward": "Ten que ser un enderezo de email válido, está aceptado o símbolo '+' (ex. persoa+etiqueta@exemplo.com)",
|
||||
"pattern_domain": "Ten que ser un nome de dominio válido (ex. dominiopropio.org)",
|
||||
"pattern_backup_archive_name": "Ten que ser un nome de ficheiro válido con 30 caracteres como máximo, alfanuméricos ou só caracteres -_.",
|
||||
"password_too_simple_4": "O contrasinal ten que ter 12 caracteres como mínimo e conter un díxito, maiúsculas, minúsculas e caracteres especiais",
|
||||
"password_too_simple_3": "O contrasinal ten que ter 8 caracteres como mínimo e conter un díxito, maiúsculas, minúsculas e caracteres especiais",
|
||||
"password_too_simple_2": "O contrasinal ten que ter 8 caracteres como mínimo e conter un díxito, maiúsculas e minúsculas",
|
||||
"password_listed": "Este contrasinal está entre os máis utilizados no mundo. Por favor elixe outro que sexa máis orixinal.",
|
||||
"packages_upgrade_failed": "Non se puideron actualizar tódolos paquetes",
|
||||
"operation_interrupted": "Foi interrumpida manualmente a operación?",
|
||||
"invalid_number": "Ten que ser un número",
|
||||
"not_enough_disk_space": "Non hai espazo libre abondo en '{path}'",
|
||||
"migrations_to_be_ran_manually": "A migración {id} ten que ser executada manualmente. Vaite a Ferramentas → Migracións na páxina webadmin, ou executa `yunohost tools migrations run`.",
|
||||
"migrations_success_forward": "Migración {id} completada",
|
||||
"migrations_skip_migration": "Omitindo migración {id}...",
|
||||
"migrations_running_forward": "Realizando migración {id}...",
|
||||
"migrations_pending_cant_rerun": "Esas migracións están pendentes, polo que non ser executadas outra vez: {ids}",
|
||||
"migrations_not_pending_cant_skip": "Esas migracións non están pendentes, polo que non poden ser omitidas: {ids}",
|
||||
"migrations_no_such_migration": "Non hai migración co nome '{id}'",
|
||||
"migrations_no_migrations_to_run": "Sen migracións a executar",
|
||||
"migrations_need_to_accept_disclaimer": "Para executar a migración {id}, tes que aceptar o seguinte aviso:\n---\n{disclaimer}\n---\nSe aceptas executar a migración, por favor volve a executar o comando coa opción '--accept-disclaimer'.",
|
||||
"migrations_must_provide_explicit_targets": "Debes proporcionar obxectivos explícitos ao utilizar '--skip' ou '--force-rerun'",
|
||||
"migrations_migration_has_failed": "A migración {id} non se completou, abortando. Erro: {exception}",
|
||||
"migrations_loading_migration": "Cargando a migración {id}...",
|
||||
"migrations_list_conflict_pending_done": "Non podes usar ao mesmo tempo '--previous' e '--done'.",
|
||||
"migrations_exclusive_options": "'--auto', '--skip', e '--force-rerun' son opcións que se exclúen unhas a outras.",
|
||||
"migrations_failed_to_load_migration": "Non se cargou a migración {id}: {error}",
|
||||
"migrations_dependencies_not_satisfied": "Executar estas migracións: '{dependencies_id}', antes da migración {id}.",
|
||||
"migrations_cant_reach_migration_file": "Non se pode acceder aos ficheiros de migración na ruta '%s'",
|
||||
"regenconf_file_manually_removed": "O ficheiro de configuración '{conf}' foi eliminado manualmente e non será creado",
|
||||
"regenconf_file_manually_modified": "O ficheiro de configuración '{conf}' foi modificado manualmente e non vai ser actualizado",
|
||||
"regenconf_file_kept_back": "Era de agardar que o ficheiro de configuración '{conf}' fose eliminado por regen-conf (categoría {category}) mais foi mantido.",
|
||||
"regenconf_file_copy_failed": "Non se puido copiar o novo ficheiro de configuración '{new}' a '{conf}'",
|
||||
"regenconf_file_backed_up": "Ficheiro de configuración '{conf}' copiado a '{backup}'",
|
||||
"postinstall_low_rootfsspace": "O sistema de ficheiros raiz ten un espazo total menor de 10GB, que é pouco! Probablemente vas quedar sen espazo moi pronto! É recomendable ter polo menos 16GB para o sistema raíz. Se queres instalar YunoHost obviando este aviso, volve a executar a postinstalación con --force-diskspace",
|
||||
"port_already_opened": "O porto {port:d} xa está aberto para conexións {ip_version}",
|
||||
"port_already_closed": "O porto {port:d} xa está pechado para conexións {ip_version}",
|
||||
"permission_require_account": "O permiso {permission} só ten sentido para usuarias cunha conta, e por tanto non pode concederse a visitantes.",
|
||||
"permission_protected": "O permiso {permission} está protexido. Non podes engadir ou eliminar o grupo visitantes a/de este permiso.",
|
||||
"permission_updated": "Permiso '{permission}' actualizado",
|
||||
"permission_update_failed": "Non se actualizou o permiso '{permission}': {error}",
|
||||
"permission_not_found": "Non se atopa o permiso '{permission}'",
|
||||
"permission_deletion_failed": "Non se puido eliminar o permiso '{permission}': {error}",
|
||||
"permission_deleted": "O permiso '{permission}' foi eliminado",
|
||||
"permission_cant_add_to_all_users": "O permiso {permission} non pode ser concecido a tódalas usuarias.",
|
||||
"permission_currently_allowed_for_all_users": "Este permiso está concedido actualmente a tódalas usuarias ademáis de a outros grupos. Probablemente queiras ben eliminar o permiso 'all_users' ou ben eliminar os outros grupos que teñen permiso.",
|
||||
"restore_failed": "Non se puido restablecer o sistema",
|
||||
"restore_extracting": "Extraendo os ficheiros necesarios desde o arquivo…",
|
||||
"restore_confirm_yunohost_installed": "Tes a certeza de querer restablecer un sistema xa instalado? [{answers}]",
|
||||
"restore_complete": "Restablecemento completado",
|
||||
"restore_cleaning_failed": "Non se puido despexar o directorio temporal de restablecemento",
|
||||
"restore_backup_too_old": "Este arquivo de apoio non pode ser restaurado porque procede dunha versión YunoHost demasiado antiga.",
|
||||
"restore_already_installed_apps": "As seguintes apps non se poden restablecer porque xa están instaladas: {apps}",
|
||||
"restore_already_installed_app": "Unha app con ID '{app}' xa está instalada",
|
||||
"regex_with_only_domain": "Agora xa non podes usar un regex para o dominio, só para ruta",
|
||||
"regex_incompatible_with_tile": "/!\\ Empacadoras! O permiso '{permission}' agora ten show_tile establecido como 'true' polo que non podes definir o regex URL como URL principal",
|
||||
"regenconf_need_to_explicitly_specify_ssh": "A configuración ssh foi modificada manualmente, pero tes que indicar explícitamente a categoría 'ssh' con --force para realmente aplicar os cambios.",
|
||||
"regenconf_pending_applying": "Aplicando a configuración pendente para categoría '{category}'...",
|
||||
"regenconf_failed": "Non se rexenerou a configuración para a categoría(s): {categories}",
|
||||
"regenconf_dry_pending_applying": "Comprobando as configuracións pendentes que deberían aplicarse á categoría '{category}'…",
|
||||
"regenconf_would_be_updated": "A configuración debería ser actualizada para a categoría '{category}'",
|
||||
"regenconf_updated": "Configuración actualizada para '{category}'",
|
||||
"regenconf_up_to_date": "A configuración xa está ao día para a categoría '{category}'",
|
||||
"regenconf_now_managed_by_yunohost": "O ficheiro de configuración '{conf}' agora está xestionado por YunoHost (categoría {category}).",
|
||||
"regenconf_file_updated": "Actualizado o ficheiro de configuración '{conf}'",
|
||||
"regenconf_file_removed": "Eliminado o ficheiro de configuración '{conf}'",
|
||||
"regenconf_file_remove_failed": "Non se puido eliminar o ficheiro de configuración '{conf}'",
|
||||
"service_enable_failed": "Non se puido facer que o servizo '{service}' se inicie automáticamente no inicio.\n\nRexistros recentes do servizo: {logs}",
|
||||
"service_disabled": "O servizo '{service}' xa non vai volver a ser iniciado ao inicio do sistema.",
|
||||
"service_disable_failed": "Non se puido iniciar o servizo '{servizo}' ao inicio.\n\nRexistro recente do servizo: {logs}",
|
||||
"service_description_yunohost-firewall": "Xestiona, abre e pecha a conexións dos portos aos servizos",
|
||||
"service_description_yunohost-api": "Xestiona as interaccións entre a interface web de YunoHost e o sistema",
|
||||
"service_description_ssh": "Permíteche conectar de xeito remoto co teu servidor a través dun terminal (protocolo SSH)",
|
||||
"service_description_slapd": "Almacena usuarias, dominios e info relacionada",
|
||||
"service_description_rspamd": "Filtra spam e outras características relacionadas co email",
|
||||
"service_description_redis-server": "Unha base de datos especial utilizada para o acceso rápido a datos, cola de tarefas e comunicación entre programas",
|
||||
"service_description_postfix": "Utilizado para enviar e recibir emails",
|
||||
"service_description_php7.3-fpm": "Executa aplicacións escritas en PHP con NGINX",
|
||||
"service_description_nginx": "Serve ou proporciona acceso a tódolos sitios web hospedados no teu servidor",
|
||||
"service_description_mysql": "Almacena datos da app (base de datos SQL)",
|
||||
"service_description_metronome": "Xestiona as contas de mensaxería instantánea XMPP",
|
||||
"service_description_fail2ban": "Protexe contra ataques de forza bruta e outro tipo de ataques desde internet",
|
||||
"service_description_dovecot": "Permite aos clientes de email acceder/obter o correo (vía IMAP e POP3)",
|
||||
"service_description_dnsmasq": "Xestiona a resolución de nomes de dominio (DNS)",
|
||||
"service_description_yunomdns": "Permíteche chegar ao teu servidor utilizando 'yunohost.local' na túa rede local",
|
||||
"service_cmd_exec_failed": "Non se puido executar o comando '{command}'",
|
||||
"service_already_stopped": "O servizo '{sevice}' xa está detido",
|
||||
"service_already_started": "O servizo '{service}' xa se está a executar",
|
||||
"service_added": "Foi engadido o servizo '{service}'",
|
||||
"service_add_failed": "Non se puido engadir o servizo '{service}'",
|
||||
"server_reboot_confirm": "Queres reiniciar o servidor inmediatamente? [{answers}]",
|
||||
"server_reboot": "Vaise reiniciar o servidor",
|
||||
"server_shutdown_confirm": "Queres apagar o servidor inmediatamente? [{answers}]",
|
||||
"server_shutdown": "Vaise apagar o servidor",
|
||||
"root_password_replaced_by_admin_password": "O contrasinal root foi substituído polo teu contrasinal de administración.",
|
||||
"root_password_desynchronized": "Mudou o contrasinal de administración, pero YunoHost non puido transferir este cambio ao contrasinal root!",
|
||||
"restore_system_part_failed": "Non se restableceu a parte do sistema '{part}'",
|
||||
"restore_running_hooks": "Executando os ganchos do restablecemento…",
|
||||
"restore_running_app_script": "Restablecendo a app '{app}'…",
|
||||
"restore_removing_tmp_dir_failed": "Non se puido eliminar o directorio temporal antigo",
|
||||
"restore_nothings_done": "Nada foi restablecido",
|
||||
"restore_not_enough_disk_space": "Non hai espazo abondo (espazo: {free_space.d} B, espazo necesario: {needed_space} B, marxe de seguridade: {margin:d} B)",
|
||||
"restore_may_be_not_enough_disk_space": "O teu sistema semella que non ten espazo abondo (libre: {free_space:d} B, espazo necesario: {needed_space:d} B, marxe de seguridade {margin:d} B)",
|
||||
"restore_hook_unavailable": "O script de restablecemento para '{part}' non está dispoñible no teu sistema nin no arquivo",
|
||||
"invalid_password": "Contrasinal non válido",
|
||||
"ldap_server_is_down_restart_it": "O servidor LDAP está caído, intenta reinicialo...",
|
||||
"ldap_server_down": "Non se chegou ao servidor LDAP",
|
||||
"global_settings_setting_security_experimental_enabled": "Activar características de seguridade experimentais (non actives isto se non sabes o que estás a facer!)",
|
||||
"yunohost_postinstall_end_tip": "Post-install completada! Para rematar a configuración considera:\n- engadir unha primeira usuaria na sección 'Usuarias' na webadmin (ou 'yunohost user create <username>' na liña de comandos);\n- diagnosticar potenciais problemas na sección 'Diagnóstico' na webadmin (ou 'yunohost diagnosis run' na liña de comandos);\n- ler 'Rematando a configuración' e 'Coñece YunoHost' na documentación da administración: https://yunohost.org/admindoc.",
|
||||
"yunohost_not_installed": "YunoHost non está instalado correctamente. Executa 'yunohost tools postinstall'",
|
||||
"yunohost_installing": "Instalando YunoHost...",
|
||||
"yunohost_configured": "YunoHost está configurado",
|
||||
"yunohost_already_installed": "YunoHost xa está instalado",
|
||||
"user_updated": "Cambiada a info da usuaria",
|
||||
"user_update_failed": "Non se actualizou usuaria {user}: {error}",
|
||||
"user_unknown": "Usuaria descoñecida: {user}",
|
||||
"user_home_creation_failed": "Non se puido crear cartafol 'home' para a usuaria",
|
||||
"user_deletion_failed": "Non se puido eliminar a usuaria {user}: {error}",
|
||||
"user_deleted": "Usuaria eliminada",
|
||||
"user_creation_failed": "Non se puido crear a usuaria {user}: {error}",
|
||||
"user_created": "Usuaria creada",
|
||||
"user_already_exists": "A usuaria '{user}' xa existe",
|
||||
"upnp_port_open_failed": "Non se puido abrir porto a través de UPnP",
|
||||
"upnp_dev_not_found": "Non se atopa dispositivo UPnP",
|
||||
"upgrading_packages": "Actualizando paquetes...",
|
||||
"upgrade_complete": "Actualización completa",
|
||||
"updating_apt_cache": "Obtendo actualizacións dispoñibles para os paquetes do sistema...",
|
||||
"update_apt_cache_warning": "Algo fallou ao actualizar a caché de APT (xestor de paquetes Debian). Aquí tes un volcado de sources.list, que podería axudar a identificar liñas problemáticas:\n{sourceslist}",
|
||||
"update_apt_cache_failed": "Non se puido actualizar a caché de APT (xestor de paquetes de Debian). Aquí tes un volcado do sources.list, que podería axudarche a identificar liñas incorrectas:\n{sourceslist}",
|
||||
"unrestore_app": "{app} non vai ser restablecida",
|
||||
"unlimit": "Sen cota",
|
||||
"unknown_main_domain_path": "Dominio ou ruta descoñecida '{app}'. Tes que indicar un dominio e ruta para poder especificar un URL para o permiso.",
|
||||
"unexpected_error": "Aconteceu un fallo non agardado: {error}",
|
||||
"unbackup_app": "{app} non vai ser gardada",
|
||||
"tools_upgrade_special_packages_completed": "Completada a actualización dos paquetes YunoHost.\nPreme [Enter] para recuperar a liña de comandos",
|
||||
"tools_upgrade_special_packages_explanation": "A actualización especial continuará en segundo plano. Non inicies outras tarefas no servidor nos seguintes ~10 minutos (depende do hardware). Após isto, podes volver a conectar na webadmin. O rexistro da actualización estará dispoñible en Ferramentas → Rexistro (na webadmin) ou con 'yunohost log list' (na liña de comandos).",
|
||||
"tools_upgrade_special_packages": "Actualizando paquetes 'special' (yunohost-related)…",
|
||||
"tools_upgrade_regular_packages_failed": "Non se actualizaron os paquetes: {packages_list}",
|
||||
"tools_upgrade_regular_packages": "Actualizando os paquetes 'regular' (non-yunohost-related)…",
|
||||
"tools_upgrade_cant_unhold_critical_packages": "Non se desbloquearon os paquetes críticos…",
|
||||
"tools_upgrade_cant_hold_critical_packages": "Non se puideron bloquear os paquetes críticos…",
|
||||
"tools_upgrade_cant_both": "Non se pode actualizar o sistema e as apps ao mesmo tempo",
|
||||
"tools_upgrade_at_least_one": "Por favor indica 'apps', ou 'system'",
|
||||
"this_action_broke_dpkg": "Esta acción rachou dpkg/APT (xestores de paquetes do sistema)... Podes intentar resolver o problema conectando a través de SSH e executando `sudo apt install --fix-broken`e/ou `sudo dpkg --configure -a`.",
|
||||
"system_username_exists": "Xa existe este nome de usuaria na lista de usuarias do sistema",
|
||||
"system_upgraded": "Sistema actualizado",
|
||||
"ssowat_conf_updated": "Actualizada a configuración SSOwat",
|
||||
"ssowat_conf_generated": "Rexenerada a configuración para SSOwat",
|
||||
"show_tile_cant_be_enabled_for_regex": "Non podes activar 'show_tile' neste intre, porque o URL para o permiso '{permission}' é un regex",
|
||||
"show_tile_cant_be_enabled_for_url_not_defined": "Non podes activar 'show_tile' neste intre, primeiro tes que definir un URL para o permiso '{permission}'",
|
||||
"service_unknown": "Servizo descoñecido '{service}'",
|
||||
"service_stopped": "Detívose o servizo '{service}'",
|
||||
"service_stop_failed": "Non se puido deter o servizo '{service}'\n\nRexistros recentes do servizo: {logs}",
|
||||
"service_started": "Iniciado o servizo '{service}'",
|
||||
"service_start_failed": "Non se puido iniciar o servizo '{service}'\n\nRexistros recentes do servizo: {logs}",
|
||||
"service_reloaded_or_restarted": "O servizo '{service}' foi recargado ou reiniciado",
|
||||
"service_reload_or_restart_failed": "Non se recargou ou reiniciou o servizo '{service}'\n\nRexistros recentes do servizo: {logs}",
|
||||
"service_restarted": "Reiniciado o servizo '{service}'",
|
||||
"service_restart_failed": "Non se reiniciou o servizo '{service}'\n\nRexistros recentes do servizo: {logs}",
|
||||
"service_reloaded": "Recargado o servizo '{service}'",
|
||||
"service_reload_failed": "Non se recargou o servizo '{service}'\n\nRexistros recentes do servizo: {logs}",
|
||||
"service_removed": "Eliminado o servizo '{service}'",
|
||||
"service_remove_failed": "Non se eliminou o servizo '{service}'",
|
||||
"service_regen_conf_is_deprecated": "'yunohost service regen-conf' xa non se utiliza! Executa 'yunohost tools regen-conf' no seu lugar.",
|
||||
"service_enabled": "O servizo '{service}' vai ser iniciado automáticamente no inicio do sistema."
|
||||
}
|
|
@ -30,7 +30,7 @@
|
|||
"app_not_correctly_installed": "{app} sembra di non essere installata correttamente",
|
||||
"app_not_properly_removed": "{app} non è stata correttamente rimossa",
|
||||
"action_invalid": "L'azione '{action}' non è valida",
|
||||
"app_removed": "{app} rimossa",
|
||||
"app_removed": "{app} disinstallata",
|
||||
"app_sources_fetch_failed": "Impossibile riportare i file sorgenti, l'URL è corretto?",
|
||||
"app_upgrade_failed": "Impossibile aggiornare {app}: {error}",
|
||||
"app_upgraded": "{app} aggiornata",
|
||||
|
@ -428,7 +428,6 @@
|
|||
"service_description_fail2ban": "Ti protegge dal brute-force e altri tipi di attacchi da Internet",
|
||||
"service_description_dovecot": "Consente ai client mail di accedere/recuperare le email (via IMAP e POP3)",
|
||||
"service_description_dnsmasq": "Gestisce la risoluzione dei domini (DNS)",
|
||||
"service_description_avahi-daemon": "Consente di raggiungere il tuo server eseguendo 'yunohost.local' sulla tua LAN",
|
||||
"server_reboot_confirm": "Il server si riavvierà immediatamente, sei sicuro? [{answers}]",
|
||||
"server_reboot": "Il server si riavvierà",
|
||||
"server_shutdown_confirm": "Il server si spegnerà immediatamente, sei sicuro? [{answers}]",
|
||||
|
@ -631,5 +630,9 @@
|
|||
"diagnosis_sshd_config_inconsistent": "Sembra che la porta SSH sia stata modificata manualmente in /etc/ssh/sshd_config: A partire da YunoHost 4.2, una nuova configurazione globale 'security.ssh.port' è disponibile per evitare di modificare manualmente la configurazione.",
|
||||
"diagnosis_sshd_config_insecure": "Sembra che la configurazione SSH sia stata modificata manualmente, ed non è sicuro dato che non contiene le direttive 'AllowGroups' o 'Allowusers' che limitano l'accesso agli utenti autorizzati.",
|
||||
"backup_create_size_estimation": "L'archivio conterrà circa {size} di dati.",
|
||||
"app_restore_script_failed": "C'è stato un errore all'interno dello script di recupero"
|
||||
"app_restore_script_failed": "C'è stato un errore all'interno dello script di recupero",
|
||||
"global_settings_setting_security_webadmin_allowlist": "Indirizzi IP con il permesso di accedere al webadmin, separati da virgola.",
|
||||
"global_settings_setting_security_webadmin_allowlist_enabled": "Permetti solo ad alcuni IP di accedere al webadmin.",
|
||||
"disk_space_not_sufficient_update": "Non c'è abbastanza spazio libero per aggiornare questa applicazione",
|
||||
"disk_space_not_sufficient_install": "Non c'è abbastanza spazio libero per installare questa applicazione"
|
||||
}
|
|
@ -193,7 +193,6 @@
|
|||
"user_unknown": "Utilizaire « {user} » desconegut",
|
||||
"user_update_failed": "Modificacion impossibla de l’utilizaire",
|
||||
"user_updated": "L’utilizaire es estat modificat",
|
||||
"service_description_avahi-daemon": "permet d’aténher vòstre servidor via yunohost.local sus vòstre ret local",
|
||||
"service_description_dnsmasq": "gerís la resolucion dels noms de domeni (DNS)",
|
||||
"updating_apt_cache": "Actualizacion de la lista dels paquets disponibles…",
|
||||
"server_reboot_confirm": "Lo servidor es per reaviar sul pic, o volètz vertadièrament ? {answers}",
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
"action_invalid": "Acção Inválida '{action}'",
|
||||
"admin_password": "Senha de administração",
|
||||
"admin_password_change_failed": "Não é possível alterar a senha",
|
||||
"admin_password_change_failed": "Não foi possível alterar a senha",
|
||||
"admin_password_changed": "A senha da administração foi alterada",
|
||||
"app_already_installed": "{app} já está instalada",
|
||||
"app_extraction_failed": "Não foi possível extrair os ficheiros para instalação",
|
||||
"app_id_invalid": "A ID da aplicação é inválida",
|
||||
"app_install_files_invalid": "Ficheiros para instalação corrompidos",
|
||||
"app_extraction_failed": "Não foi possível extrair os arquivos para instalação",
|
||||
"app_id_invalid": "App ID invaĺido",
|
||||
"app_install_files_invalid": "Esses arquivos não podem ser instalados",
|
||||
"app_manifest_invalid": "Manifesto da aplicação inválido: {error}",
|
||||
"app_not_installed": "{app} não está instalada",
|
||||
"app_removed": "{app} removida com êxito",
|
||||
"app_sources_fetch_failed": "Incapaz obter os ficheiros fonte",
|
||||
"app_not_installed": "Não foi possível encontrar {app} na lista de aplicações instaladas: {all_apps}",
|
||||
"app_removed": "{app} desinstalada",
|
||||
"app_sources_fetch_failed": "Não foi possível carregar os arquivos de código fonte, a URL está correta?",
|
||||
"app_unknown": "Aplicação desconhecida",
|
||||
"app_upgrade_failed": "Não foi possível atualizar {app}",
|
||||
"app_upgraded": "{app} atualizada com sucesso",
|
||||
"app_upgrade_failed": "Não foi possível atualizar {app}: {error}",
|
||||
"app_upgraded": "{app} atualizado",
|
||||
"ask_firstname": "Primeiro nome",
|
||||
"ask_lastname": "Último nome",
|
||||
"ask_main_domain": "Domínio principal",
|
||||
|
@ -108,14 +108,14 @@
|
|||
"backup_hook_unknown": "Gancho de backup '{hook}' desconhecido",
|
||||
"backup_nothings_done": "Não há nada para guardar",
|
||||
"backup_output_directory_forbidden": "Diretório de saída proibido. Os backups não podem ser criados em /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var ou /home/yunohost.backup/archives subpastas",
|
||||
"app_already_installed_cant_change_url": "Este aplicativo já está instalado. A URL não pode ser alterada apenas por esta função. Olhe para o `app changeurl` se estiver disponível.",
|
||||
"app_already_installed_cant_change_url": "Este aplicativo já está instalado. A URL não pode ser alterada apenas por esta função. Confira em `app changeurl` se está disponível.",
|
||||
"app_already_up_to_date": "{app} já está atualizado",
|
||||
"app_argument_choice_invalid": "Escolha inválida para o argumento '{name}', deve ser um dos {choices}",
|
||||
"app_argument_invalid": "Valor inválido de argumento '{name}': {error}",
|
||||
"app_argument_choice_invalid": "Use uma das opções '{choices}' para o argumento '{name}'",
|
||||
"app_argument_invalid": "Escolha um valor válido para o argumento '{name}': {error}",
|
||||
"app_argument_required": "O argumento '{name}' é obrigatório",
|
||||
"app_change_url_failed_nginx_reload": "Falha ao reiniciar o nginx. Aqui está o retorno de 'nginx -t':\n{nginx_errors}",
|
||||
"app_location_unavailable": "Esta url não está disponível ou está em conflito com outra aplicação já instalada",
|
||||
"app_upgrade_app_name": "Atualizando aplicação {app}…",
|
||||
"app_change_url_failed_nginx_reload": "Não foi possível reiniciar o nginx. Aqui está o retorno de 'nginx -t':\n{nginx_errors}",
|
||||
"app_location_unavailable": "Esta url ou não está disponível ou está em conflito com outra(s) aplicação(ões) já instalada(s):\n{apps}",
|
||||
"app_upgrade_app_name": "Atualizando {app}…",
|
||||
"app_upgrade_some_app_failed": "Não foi possível atualizar algumas aplicações",
|
||||
"backup_abstract_method": "Este metodo de backup ainda não foi implementado",
|
||||
"backup_app_failed": "Não foi possível fazer o backup dos aplicativos '{app}'",
|
||||
|
@ -129,5 +129,40 @@
|
|||
"app_change_url_identical_domains": "O antigo e o novo domínio / url_path são idênticos ('{domain}{path}'), nada para fazer.",
|
||||
"password_too_simple_1": "A senha precisa ter pelo menos 8 caracteres",
|
||||
"admin_password_too_long": "Escolha uma senha que contenha menos de 127 caracteres",
|
||||
"aborting": "Abortando."
|
||||
"aborting": "Abortando.",
|
||||
"app_change_url_no_script": "A aplicação '{app_name}' ainda não permite modificar a URL. Talvez devesse atualizá-la.",
|
||||
"app_argument_password_no_default": "Erro ao interpretar argumento da senha '{name}': O argumento da senha não pode ter um valor padrão por segurança",
|
||||
"app_action_cannot_be_ran_because_required_services_down": "Estes serviços devem estar funcionado para executar esta ação: {services}. Tente reiniciá-los para continuar (e possivelmente investigar o porquê de não estarem funcionado).",
|
||||
"app_action_broke_system": "Esta ação parece ter quebrado estes serviços importantes: {services}",
|
||||
"already_up_to_date": "Nada a ser feito. Tudo já está atualizado.",
|
||||
"additional_urls_already_removed": "A URL adicional '{url}'já está removida para a permissão '{permission}'",
|
||||
"additional_urls_already_added": "A URL adicional '{url}' já está adicionada para a permissão '{permission}'",
|
||||
"app_install_script_failed": "Ocorreu um erro dentro do script de instalação do aplicativo",
|
||||
"app_install_failed": "Não foi possível instalar {app}: {error}",
|
||||
"app_full_domain_unavailable": "Desculpe, esse app deve ser instalado num domínio próprio mas já há outros apps instalados no domínio '{domain}'. Você pode usar um subdomínio dedicado a esse aplicativo.",
|
||||
"app_change_url_success": "A URL agora é {domain}{path}",
|
||||
"apps_catalog_obsolete_cache": "O cache do catálogo de aplicações está vazio ou obsoleto.",
|
||||
"apps_catalog_failed_to_download": "Não foi possível fazer o download do catálogo de aplicações {apps_catalog}: {error}",
|
||||
"apps_catalog_updating": "Atualizado o catálogo de aplicações…",
|
||||
"apps_catalog_init_success": "Catálogo de aplicações do sistema inicializado!",
|
||||
"apps_already_up_to_date": "Todas as aplicações já estão atualizadas",
|
||||
"app_packaging_format_not_supported": "Essa aplicação não pode ser instalada porque o formato dela não é suportado pela sua versão do YunoHost. Considere atualizar seu sistema.",
|
||||
"app_upgrade_script_failed": "Ocorreu um erro dentro do script de atualização da aplicação",
|
||||
"app_upgrade_several_apps": "As seguintes aplicações serão atualizadas: {apps}",
|
||||
"app_start_restore": "Restaurando {app}...",
|
||||
"app_start_backup": "Obtendo os arquivos para fazer o backup de {app}...",
|
||||
"app_start_remove": "Removendo {app}...",
|
||||
"app_start_install": "Instalando {app}...",
|
||||
"app_restore_script_failed": "Ocorreu um erro dentro do script de restauração da aplicação",
|
||||
"app_restore_failed": "Não foi possível restaurar {app}: {error}",
|
||||
"app_remove_after_failed_install": "Removendo a aplicação após a falha da instalação...",
|
||||
"app_requirements_unmeet": "Os requisitos para a aplicação {app} não foram satisfeitos, o pacote {pkgname} ({version}) devem ser {spec}",
|
||||
"app_not_upgraded": "Não foi possível atualizar a aplicação '{failed_app}' e, como consequência, a atualização das seguintes aplicações foi cancelada: {apps}",
|
||||
"app_manifest_install_ask_is_public": "Essa aplicação deve ser visível para visitantes anônimos?",
|
||||
"app_manifest_install_ask_admin": "Escolha um usuário de administrador para essa aplicação",
|
||||
"app_manifest_install_ask_password": "Escolha uma senha de administrador para essa aplicação",
|
||||
"app_manifest_install_ask_path": "Escolha o caminho da url (depois do domínio) em que essa aplicação deve ser instalada",
|
||||
"app_manifest_install_ask_domain": "Escolha o domínio em que esta aplicação deve ser instalada",
|
||||
"app_label_deprecated": "Este comando está deprecado! Por favor use o novo comando 'yunohost user permission update' para gerenciar a etiqueta da aplicação.",
|
||||
"app_make_default_location_already_used": "Não foi passível fazer a aplicação '{app}' ser a padrão no domínio, '{domain}' já está sendo usado por '{other_app}'"
|
||||
}
|
642
locales/uk.json
642
locales/uk.json
|
@ -1 +1,641 @@
|
|||
{}
|
||||
{
|
||||
"app_manifest_install_ask_domain": "Оберіть домен, в якому треба встановити цей застосунок",
|
||||
"app_manifest_invalid": "Щось не так з маніфестом застосунку: {error}",
|
||||
"app_location_unavailable": "Ця URL-адреса або недоступна, або конфліктує з уже встановленим застосунком (застосунками):\n{apps}",
|
||||
"app_label_deprecated": "Ця команда застаріла! Будь ласка, використовуйте нову команду 'yunohost user permission update' для управління заголовком застосунку.",
|
||||
"app_make_default_location_already_used": "Неможливо зробити '{app}' типовим застосунком на домені, '{domain}' вже використовується '{other_app}'",
|
||||
"app_install_script_failed": "Сталася помилка в скрипті встановлення застосунку",
|
||||
"app_install_failed": "Неможливо встановити {app}: {error}",
|
||||
"app_install_files_invalid": "Ці файли не можуть бути встановлені",
|
||||
"app_id_invalid": "Неприпустимий ID застосунку",
|
||||
"app_full_domain_unavailable": "Вибачте, цей застосунок повинен бути встановлений на власному домені, але інші застосунки вже встановлені на домені '{domain}'. Замість цього ви можете використовувати піддомен, призначений для цього застосунку.",
|
||||
"app_extraction_failed": "Не вдалося витягти файли встановлення",
|
||||
"app_change_url_success": "URL-адреса {app} тепер {domain}{path}",
|
||||
"app_change_url_no_script": "Застосунок '{app_name}' поки не підтримує зміну URL-адрес. Можливо, вам слід оновити його.",
|
||||
"app_change_url_identical_domains": "Старий і новий domain/url_path збігаються ('{domain}{path}'), нічого робити не треба.",
|
||||
"app_change_url_failed_nginx_reload": "Не вдалося перезавантажити NGINX. Ось результат 'nginx -t':\n{nginx_errors}",
|
||||
"app_argument_required": "Аргумент '{name}' необхідний",
|
||||
"app_argument_password_no_default": "Помилка під час розбору аргументу пароля '{name}': аргумент пароля не може мати типове значення з причин безпеки",
|
||||
"app_argument_invalid": "Виберіть правильне значення для аргументу '{name}': {error}",
|
||||
"app_argument_choice_invalid": "Використовуйте один з цих варіантів '{choices}' для аргументу '{name}'",
|
||||
"app_already_up_to_date": "{app} має найостаннішу версію",
|
||||
"app_already_installed_cant_change_url": "Цей застосунок уже встановлено. URL-адреса не може бути змінена тільки цією функцією. Перевірте в `app changeurl`, якщо вона доступна.",
|
||||
"app_already_installed": "{app} уже встановлено",
|
||||
"app_action_broke_system": "Ця дія, схоже, порушила роботу наступних важливих служб: {services}",
|
||||
"app_action_cannot_be_ran_because_required_services_down": "Для виконання цієї дії повинні бути запущені наступні необхідні служби: {services}. Спробуйте перезапустити їх, щоб продовжити (і, можливо, з'ясувати, чому вони не працюють).",
|
||||
"already_up_to_date": "Нічого не потрібно робити. Все вже актуально.",
|
||||
"admin_password_too_long": "Будь ласка, виберіть пароль коротше 127 символів",
|
||||
"admin_password_changed": "Пароль адміністратора було змінено",
|
||||
"admin_password_change_failed": "Неможливо змінити пароль",
|
||||
"admin_password": "Пароль адміністратора",
|
||||
"additional_urls_already_removed": "Додаткова URL-адреса '{url}' вже видалена в додатковій URL-адресі для дозволу '{permission}'",
|
||||
"additional_urls_already_added": "Додаткова URL-адреса '{url}' вже додана в додаткову URL-адресу для дозволу '{permission}'",
|
||||
"action_invalid": "Неприпустима дія '{action}'",
|
||||
"aborting": "Переривання.",
|
||||
"diagnosis_description_web": "Мережа",
|
||||
"service_reloaded_or_restarted": "Служба '{service}' була перезавантажена або перезапущено",
|
||||
"service_reload_or_restart_failed": "Не вдалося перезавантажити або перезапустити службу '{service}' Recent service logs: {logs}",
|
||||
"service_restarted": "Служба '{service}' перезапущено",
|
||||
"service_restart_failed": "Не вдалося запустити службу '{service}' Недавні журнали служб: {logs}",
|
||||
"service_reloaded": "Служба '{service}' перезавантажена",
|
||||
"service_reload_failed": "Не вдалося перезавантажити службу '{service}' Останні журнали служби: {logs}",
|
||||
"service_removed": "Служба '{service}' вилучена",
|
||||
"service_remove_failed": "Не вдалося видалити службу '{service}'",
|
||||
"service_regen_conf_is_deprecated": "'Yunohost service regen-conf' застарів! Будь ласка, використовуйте 'yunohost tools regen-conf' замість цього.",
|
||||
"service_enabled": "Служба '{service}' тепер буде автоматично запускатися при завантаженні системи.",
|
||||
"service_enable_failed": "Неможливо змусити службу '{service}' автоматично запускатися при завантаженні. Недавні журнали служб: {logs}",
|
||||
"service_disabled": "Служба '{service}' більше не буде запускатися при завантаженні системи.",
|
||||
"service_disable_failed": "Неможливо змусити службу '{service} \"не запускатися при завантаженні. Останні журнали служби: {logs}",
|
||||
"service_description_yunohost-firewall": "Управляє відкритими і закритими портами підключення до сервісів",
|
||||
"service_description_yunohost-api": "Управляє взаємодією між веб-інтерфейсом YunoHost і системою",
|
||||
"service_description_ssh": "Дозволяє віддалено підключатися до сервера через термінал (протокол SSH)",
|
||||
"service_description_slapd": "Зберігає користувачів, домени і пов'язану з ними інформацію",
|
||||
"service_description_rspamd": "Фільтрує спам і інші функції, пов'язані з електронною поштою",
|
||||
"service_description_redis-server": "Спеціалізована база даних, яка використовується для швидкого доступу до даних, черги завдань і зв'язку між програмами",
|
||||
"service_description_postfix": "Використовується для відправки та отримання електронної пошти",
|
||||
"service_description_php7.3-fpm": "Запускає програми, написані на мові програмування PHP, за допомогою NGINX",
|
||||
"service_description_nginx": "Обслуговує або надає доступ до всіх веб-сайтів, розміщених на вашому сервері",
|
||||
"service_description_mysql": "Зберігає дані додатків (база даних SQL)",
|
||||
"service_description_metronome": "Служба захисту миттєвого обміну повідомленнями XMPP",
|
||||
"service_description_fail2ban": "Захист від перебору та інших видів атак з Інтернету",
|
||||
"service_description_dovecot": "Дозволяє поштовим клієнтам отримувати доступ до електронної пошти (через IMAP і POP3)",
|
||||
"service_description_dnsmasq": "Обробляє дозвіл доменних імен (DNS)",
|
||||
"service_description_yunomdns": "Дозволяє вам отримати доступ до вашого сервера, використовуючи 'yunohost.local' у вашій локальній мережі",
|
||||
"service_cmd_exec_failed": "Не вдалося виконати команду '{команда}'",
|
||||
"service_already_stopped": "Служба '{service}' вже зупинена",
|
||||
"service_already_started": "Служба '{service}' вже запущена",
|
||||
"service_added": "Служба '{service}' була додана",
|
||||
"service_add_failed": "Не вдалося додати службу '{service}'",
|
||||
"server_reboot_confirm": "Сервер негайно перезавантажиться, ви впевнені? [{Відповіді}]",
|
||||
"server_reboot": "сервер перезавантажиться",
|
||||
"server_shutdown_confirm": "Сервер буде негайно виключений, ви впевнені? [{Відповіді}].",
|
||||
"server_shutdown": "сервер вимкнеться",
|
||||
"root_password_replaced_by_admin_password": "Ваш кореневої пароль був замінений на пароль адміністратора.",
|
||||
"root_password_desynchronized": "Пароль адміністратора був змінений, але YunoHost не зміг поширити це на пароль root!",
|
||||
"restore_system_part_failed": "Не вдалося відновити системну частину '{part}'.",
|
||||
"restore_running_hooks": "Запуск хуков відновлення…",
|
||||
"restore_running_app_script": "Відновлення програми \"{app} '…",
|
||||
"restore_removing_tmp_dir_failed": "Неможливо видалити старий тимчасовий каталог",
|
||||
"restore_nothings_done": "Нічого не було відновлено",
|
||||
"restore_not_enough_disk_space": "Недостатньо місця (простір: {free_space: d} B, необхідний простір: {needed_space: d} B, маржа безпеки: {margin: d} B)",
|
||||
"restore_may_be_not_enough_disk_space": "Схоже, у вашій системі недостатньо місця (вільного: {free_space: d} B, необхідний простір: {needed_space: d} B, запас міцності: {margin: d} B)",
|
||||
"restore_hook_unavailable": "Сценарій відновлення для '{part}' недоступним у вашій системі і в архіві його теж немає",
|
||||
"restore_failed": "Не вдалося відновити систему",
|
||||
"restore_extracting": "Витяг необхідних файлів з архіву…",
|
||||
"restore_confirm_yunohost_installed": "Ви дійсно хочете відновити вже встановлену систему? [{Відповіді}].",
|
||||
"restore_complete": "відновлення завершено",
|
||||
"restore_cleaning_failed": "Не вдалося очистити тимчасовий каталог відновлення",
|
||||
"restore_backup_too_old": "Цей архів резервних копій не може бути відновлений, бо він отриманий з дуже старою версією YunoHost.",
|
||||
"restore_already_installed_apps": "Наступні програми не можуть бути відновлені, тому що вони вже встановлені: {apps}",
|
||||
"restore_already_installed_app": "Додаток з ідентифікатором \"{app} 'вже встановлено",
|
||||
"regex_with_only_domain": "Ви не можете використовувати regex для домену, тільки для шляху.",
|
||||
"regex_incompatible_with_tile": "/! \\ Packagers! Дозвіл '{permission}' має значення show_tile 'true', тому ви не можете визначити regex URL в якості основного URL.",
|
||||
"regenconf_need_to_explicitly_specify_ssh": "Конфігурація ssh була змінена вручну, але вам потрібно явно вказати категорію 'ssh' з --force, щоб застосувати зміни.",
|
||||
"regenconf_pending_applying": "Застосування очікує конфігурації для категорії '{категорія}'...",
|
||||
"regenconf_failed": "Не вдалося відновити конфігурацію для категорії (категорій): {categories}",
|
||||
"regenconf_dry_pending_applying": "Перевірка очікує конфігурації, яка була б застосована для категорії '{категорія}'…",
|
||||
"regenconf_would_be_updated": "Конфігурація була б оновлена для категорії '{категорія}'",
|
||||
"regenconf_updated": "Конфігурація оновлена для категорії '{category}'",
|
||||
"regenconf_up_to_date": "Конфігурація вже оновлена для категорії '{категорія}'",
|
||||
"regenconf_now_managed_by_yunohost": "Конфігураційний файл '{conf}' тепер управляється YunoHost (категорія {category}).",
|
||||
"regenconf_file_updated": "Конфігураційний файл '{conf}' оновлений",
|
||||
"regenconf_file_removed": "Конфігураційний файл '{conf}' видалений",
|
||||
"regenconf_file_remove_failed": "Неможливо видалити файл конфігурації '{conf}'",
|
||||
"regenconf_file_manually_removed": "Конфігураційний файл '{conf}' був видалений вручну і не буде створено",
|
||||
"regenconf_file_manually_modified": "Конфігураційний файл '{conf}' був змінений вручну і не буде оновлено",
|
||||
"regenconf_file_kept_back": "Конфігураційний файл '{conf}' повинен був бути вилучений regen-conf (категорія {category}), але був збережений.",
|
||||
"regenconf_file_copy_failed": "Не вдалося скопіювати новий файл конфігурації '{new}' в '{conf}'",
|
||||
"regenconf_file_backed_up": "Конфігураційний файл '{conf}' збережений в '{backup}'",
|
||||
"postinstall_low_rootfsspace": "Загальна площа кореневої файлової системи становить менше 10 ГБ, що викликає занепокоєння! Швидше за все, дисковий простір закінчиться дуже швидко! Рекомендується мати не менше 16 ГБ для кореневої файлової системи. Якщо ви хочете встановити YunoHost, незважаючи на це попередження, повторно запустіть постінсталляцію з параметром --force-diskspace",
|
||||
"port_already_opened": "Порт {port: d} вже відкритий для з'єднань {ip_version}.",
|
||||
"port_already_closed": "Порт {port: d} вже закритий для з'єднань {ip_version}.",
|
||||
"permission_require_account": "Дозвіл {permission} має сенс тільки для користувачів, що мають обліковий запис, і тому не може бути включено для відвідувачів.",
|
||||
"permission_protected": "Дозвіл {permission} захищено. Ви не можете додавати або видаляти групу відвідувачів в/з цього дозволу.",
|
||||
"permission_updated": "Дозвіл '{permission}' оновлено",
|
||||
"permission_update_failed": "Не вдалося оновити дозвіл '{permission}': {error}",
|
||||
"permission_not_found": "Дозвіл '{permission}', не знайдено",
|
||||
"permission_deletion_failed": "Не вдалося видалити дозвіл '{permission}': {помилка}",
|
||||
"permission_deleted": "Дозвіл '{permission}' видалено",
|
||||
"permission_cant_add_to_all_users": "Дозвіл {permission} не може бути додано всім користувачам.",
|
||||
"permission_currently_allowed_for_all_users": "В даний час цей дозвіл надається всім користувачам на додаток до інших груп. Ймовірно, вам потрібно або видалити дозвіл 'all_users', або видалити інші групи, яким воно зараз надано.",
|
||||
"permission_creation_failed": "Не вдалося створити дозвіл '{permission}': {error}",
|
||||
"permission_created": "Дозвіл '{permission}' створено",
|
||||
"permission_cannot_remove_main": "Видалення основного дозволу заборонено",
|
||||
"permission_already_up_to_date": "Дозвіл не було оновлено, тому що запити на додавання/видалення вже відповідають поточному стану.",
|
||||
"permission_already_exist": "Дозвіл '{permission}' вже існує",
|
||||
"permission_already_disallowed": "Група '{group}' вже має дозвіл \"{permission} 'відключено",
|
||||
"permission_already_allowed": "Для гурту \"{group} 'вже включено дозвіл' {permission} '",
|
||||
"pattern_password_app": "На жаль, паролі не можуть містити такі символи: {forbidden_chars}",
|
||||
"pattern_username": "Повинен складатися тільки з букв і цифр в нижньому регістрі і символів підкреслення.",
|
||||
"pattern_positive_number": "Повинно бути позитивним числом",
|
||||
"pattern_port_or_range": "Повинен бути дійсний номер порту (наприклад, 0-65535) або діапазон портів (наприклад, 100: 200).",
|
||||
"pattern_password": "Повинен бути довжиною не менше 3 символів",
|
||||
"pattern_mailbox_quota": "Повинен бути розмір з суфіксом b/k/M/G/T або 0, щоб не мати квоти.",
|
||||
"pattern_lastname": "Повинна бути дійсне прізвище",
|
||||
"pattern_firstname": "Повинно бути дійсне ім'я",
|
||||
"pattern_email": "Повинен бути дійсною адресою електронної пошти, без символу '+' (наприклад, someone@example.com ).",
|
||||
"pattern_email_forward": "Повинен бути дійсну адресу електронної пошти, символ '+' приймається (наприклад, someone+tag@example.com )",
|
||||
"pattern_domain": "Повинно бути дійсне доменне ім'я (наприклад, my-domain.org)",
|
||||
"pattern_backup_archive_name": "Повинно бути правильне ім'я файлу, що містить не більше 30 символів, тільки букви і цифри символи і символ -_.",
|
||||
"password_too_simple_4": "Пароль повинен бути довжиною не менше 12 символів і містити цифру, верхні, нижні і спеціальні символи.",
|
||||
"password_too_simple_3": "Пароль повинен бути довжиною не менше 8 символів і містити цифру, верхні, нижні і спеціальні символи",
|
||||
"password_too_simple_2": "Пароль повинен складатися не менше ніж з 8 символів і містити цифру, верхній і нижній символи",
|
||||
"password_too_simple_1": "Пароль повинен складатися не менше ніж з 8 символів",
|
||||
"password_listed": "Цей пароль входить в число найбільш часто використовуваних паролів в світі. Будь ласка, виберіть щось більш унікальне.",
|
||||
"packages_upgrade_failed": "Не вдалося оновити всі пакети",
|
||||
"operation_interrupted": "Операція була перервана вручну?",
|
||||
"invalid_number": "Повинно бути число",
|
||||
"not_enough_disk_space": "Недостатньо вільного місця на \"{шлях} '.",
|
||||
"migrations_to_be_ran_manually": "Міграція {id} повинна бути запущена вручну. Будь ласка, перейдіть в розділ Інструменти → Міграції на сторінці веб-адміністратора або виконайте команду `yunohost tools migrations run`.",
|
||||
"migrations_success_forward": "Міграція {id} завершена",
|
||||
"migrations_skip_migration": "Пропуск міграції {id}...",
|
||||
"migrations_running_forward": "Виконання міграції {id}...",
|
||||
"migrations_pending_cant_rerun": "Ці міграції ще не завершені, тому не можуть бути запущені знову: {ids}",
|
||||
"migrations_not_pending_cant_skip": "Ці міграції не очікують виконання, тому не можуть бути пропущені: {ids}",
|
||||
"migrations_no_such_migration": "Не існує міграції під назвою '{id}'.",
|
||||
"migrations_no_migrations_to_run": "Немає міграцій для запуску",
|
||||
"migrations_need_to_accept_disclaimer": "Щоб запустити міграцію {id}, ви повинні прийняти наступний відмова від відповідальності: --- {disclaimer} --- Якщо ви згодні запустити міграцію, будь ласка, повторіть команду з опцією '--accept-disclaimer'.",
|
||||
"migrations_must_provide_explicit_targets": "Ви повинні вказати явні цілі при використанні '--skip' або '--force-rerun'.",
|
||||
"migrations_migration_has_failed": "Міграція {id} не завершена, переривається. Помилка: {exception}.",
|
||||
"migrations_loading_migration": "Завантаження міграції {id}...",
|
||||
"migrations_list_conflict_pending_done": "Ви не можете одночасно використовувати '--previous' і '--done'.",
|
||||
"migrations_exclusive_options": "'--Auto', '--skip' і '--force-rerun' є взаємовиключними опціями.",
|
||||
"migrations_failed_to_load_migration": "Не вдалося завантажити міграцію {id}: {error}",
|
||||
"migrations_dependencies_not_satisfied": "Запустіть ці міграції: '{dependencies_id}', перед міграцією {id}.",
|
||||
"migrations_cant_reach_migration_file": "Не вдалося отримати доступ до файлів міграцій по шляху '% s'.",
|
||||
"migrations_already_ran": "Ці міграції вже виконані: {ids}",
|
||||
"migration_0019_slapd_config_will_be_overwritten": "Схоже, що ви вручну відредагували конфігурацію slapd. Для цього критичного переходу YunoHost повинен примусово оновити конфігурацію slapd. Оригінальні файли будуть збережені в {conf_backup_folder}.",
|
||||
"migration_0019_add_new_attributes_in_ldap": "Додавання нових атрибутів для дозволів в базі даних LDAP",
|
||||
"migration_0018_failed_to_reset_legacy_rules": "Не вдалося скинути застарілі правила iptables: {error}",
|
||||
"migration_0018_failed_to_migrate_iptables_rules": "Не вдалося перенести застарілі правила iptables в nftables: {error}",
|
||||
"migration_0017_not_enough_space": "Звільніть достатньо місця в {path} для запуску міграції.",
|
||||
"migration_0017_postgresql_11_not_installed": "PostgreSQL 9.6 встановлений, але не postgresql 11‽ Можливо, у вашій системі відбулося щось дивне: (...",
|
||||
"migration_0017_postgresql_96_not_installed": "PostgreSQL ні встановлено у вашій системі. Нічого не потрібно робити.",
|
||||
"migration_0015_weak_certs": "Було виявлено, що такі сертифікати все ще використовують слабкі алгоритми підпису і повинні бути оновлені для сумісності з наступною версією nginx: {certs}",
|
||||
"migration_0015_cleaning_up": "Очищення кеш-пам'яті і пакетів, які більше не потрібні...",
|
||||
"migration_0015_specific_upgrade": "Початок поновлення системних пакетів, які повинні бути оновлені незалежно...",
|
||||
"migration_0015_modified_files": "Зверніть увагу, що такі файли були змінені вручну і можуть бути перезаписані після поновлення: {manually_modified_files}.",
|
||||
"migration_0015_problematic_apps_warning": "Зверніть увагу, що були виявлені наступні, можливо, проблемні встановлені додатки. Схоже, що вони не були встановлені з каталогу додатків YunoHost або не зазначені як \"робочі\". Отже, не можна гарантувати, що вони будуть працювати після оновлення: {problematic_apps}.",
|
||||
"migration_0015_general_warning": "Будь ласка, зверніть увагу, що ця міграція є делікатною операцією. Команда YunoHost зробила все можливе, щоб перевірити і протестувати її, але міграція все ще може порушити частина системи або її додатків. Тому рекомендується: - Виконати резервне копіювання всіх важливих даних або додатків. Більш детальна інформація на сайті https://yunohost.org/backup; - Наберіться терпіння після запуску міграції: В залежності від вашого підключення до Інтернету і апаратного забезпечення, оновлення може зайняти до декількох годин.",
|
||||
"migration_0015_system_not_fully_up_to_date": "Ваша система не повністю оновлена. Будь ласка, виконайте регулярне оновлення перед запуском міграції на Buster.",
|
||||
"migration_0015_not_enough_free_space": "Вільного місця в/var/досить мало! У вас повинно бути не менше 1 ГБ вільного місця, щоб запустити цю міграцію.",
|
||||
"migration_0015_not_stretch": "Поточний дистрибутив Debian не є Stretch!",
|
||||
"migration_0015_yunohost_upgrade": "Починаємо оновлення ядра YunoHost...",
|
||||
"migration_0015_still_on_stretch_after_main_upgrade": "Щось пішло не так під час основного поновлення, система, схоже, все ще знаходиться на Debian Stretch",
|
||||
"migration_0015_main_upgrade": "Початок основного поновлення...",
|
||||
"migration_0015_patching_sources_list": "Виправлення sources.lists...",
|
||||
"migration_0015_start": "Початок міграції на Buster",
|
||||
"migration_update_LDAP_schema": "Оновлення схеми LDAP...",
|
||||
"migration_ldap_rollback_success": "Система відкотилася.",
|
||||
"migration_ldap_migration_failed_trying_to_rollback": "Не вдалося виконати міграцію... спроба відкату системи.",
|
||||
"migration_ldap_can_not_backup_before_migration": "Не вдалося завершити резервне копіювання системи перед невдалої міграцією. Помилка: {error}",
|
||||
"migration_ldap_backup_before_migration": "Створення резервної копії бази даних LDAP і установки додатків перед фактичної міграцією.",
|
||||
"migration_description_0020_ssh_sftp_permissions": "Додайте підтримку дозволів SSH і SFTP",
|
||||
"migration_description_0019_extend_permissions_features": "Розширення/переробка системи управління дозволами додатків",
|
||||
"migration_description_0018_xtable_to_nftable": "Перенесення старих правил мережевого трафіку в нову систему nftable",
|
||||
"migration_description_0017_postgresql_9p6_to_11": "Перенесення баз даних з PostgreSQL 9.6 на 11",
|
||||
"migration_description_0016_php70_to_php73_pools": "Перенесіть php7.0-fpm 'pool' conf файли на php7.3",
|
||||
"migration_description_0015_migrate_to_buster": "Оновлення системи до Debian Buster і YunoHost 4.x",
|
||||
"migrating_legacy_permission_settings": "Перенесення застарілих налаштувань дозволів...",
|
||||
"main_domain_changed": "Основний домен був змінений",
|
||||
"main_domain_change_failed": "Неможливо змінити основний домен",
|
||||
"mail_unavailable": "Ця електронна адреса зарезервований і буде автоматично виділено найпершого користувачеві",
|
||||
"mailbox_used_space_dovecot_down": "Поштова служба Dovecot повинна бути запущена, якщо ви хочете отримати використане місце в поштовій скриньці.",
|
||||
"mailbox_disabled": "Електронна пошта відключена для користувача {user}",
|
||||
"mail_forward_remove_failed": "Не вдалося видалити переадресацію електронної пошти '{mail}'",
|
||||
"mail_domain_unknown": "Неправильну адресу електронної пошти для домену '{domain}'. Будь ласка, використовуйте домен, адмініструється цим сервером.",
|
||||
"mail_alias_remove_failed": "Не вдалося видалити псевдонім електронної пошти '{mail}'",
|
||||
"log_tools_reboot": "перезавантажити сервер",
|
||||
"log_tools_shutdown": "Вимкнути ваш сервер",
|
||||
"log_tools_upgrade": "Оновлення системних пакетів",
|
||||
"log_tools_postinstall": "Постінсталляція вашого сервера YunoHost",
|
||||
"log_tools_migrations_migrate_forward": "запустіть міграції",
|
||||
"log_domain_main_domain": "Зробити '{}' основним доменом",
|
||||
"log_user_permission_reset": "Скинути дозвіл \"{} '",
|
||||
"log_user_permission_update": "Оновити доступи для дозволу '{}'",
|
||||
"log_user_update": "Оновити інформацію для користувача '{}'",
|
||||
"log_user_group_update": "Оновити групу '{}'",
|
||||
"log_user_group_delete": "Видалити групу \"{} '",
|
||||
"log_user_group_create": "Створити групу '{}'",
|
||||
"log_user_delete": "Видалити користувача '{}'",
|
||||
"log_user_create": "Додати користувача '{}'",
|
||||
"log_regen_conf": "Регенерувати системні конфігурації '{}'",
|
||||
"log_letsencrypt_cert_renew": "Оновити сертифікат Let's Encrypt на домені '{}'",
|
||||
"log_selfsigned_cert_install": "Встановити самоподпісанний сертифікат на домені '{}'",
|
||||
"log_permission_url": "Оновити URL, пов'язаний з дозволом '{}'",
|
||||
"log_permission_delete": "Видалити дозвіл \"{} '",
|
||||
"log_permission_create": "Створити дозвіл \"{} '",
|
||||
"log_letsencrypt_cert_install": "Встановіть сертифікат Let's Encrypt на домен '{}'",
|
||||
"log_dyndns_update": "Оновити IP, пов'язаний з вашим піддоменом YunoHost '{}'",
|
||||
"log_dyndns_subscribe": "Підписка на піддомен YunoHost '{}'",
|
||||
"log_domain_remove": "Видалити домен '{}' з конфігурації системи",
|
||||
"log_domain_add": "Додати домен '{}' в конфігурацію системи",
|
||||
"log_remove_on_failed_install": "Видалити '{}' після невдалої установки",
|
||||
"log_remove_on_failed_restore": "Видалити '{}' після невдалого відновлення з резервного архіву",
|
||||
"log_backup_restore_app": "Відновлення '{}' з архіву резервних копій",
|
||||
"log_backup_restore_system": "Відновлення системи з резервного архіву",
|
||||
"log_backup_create": "Створення резервного архіву",
|
||||
"log_available_on_yunopaste": "Цей журнал тепер доступний за посиланням {url}",
|
||||
"log_app_config_apply": "Застосувати конфігурацію до додатка \"{} '",
|
||||
"log_app_config_show_panel": "Показати панель конфігурації програми \"{} '",
|
||||
"log_app_action_run": "Активації дії додатка \"{} '",
|
||||
"log_app_makedefault": "Зробити '{}' додатком за замовчуванням",
|
||||
"log_app_upgrade": "Оновити додаток '{}'",
|
||||
"log_app_remove": "Для видалення програми '{}'",
|
||||
"log_app_install": "Встановіть додаток '{}'",
|
||||
"log_app_change_url": "Змініть URL-адресу додатка \"{} '",
|
||||
"log_operation_unit_unclosed_properly": "Блок операцій не був закритий належним чином",
|
||||
"log_does_exists": "Немає журналу операцій з ім'ям '{log}', використовуйте 'yunohost log list', щоб подивитися всі публічні журнали операцій",
|
||||
"log_help_to_get_failed_log": "Операція '{desc}' не може бути завершена. Будь ласка, поділіться повним журналом цієї операції, використовуючи команду 'yunohost log share {name}', щоб отримати допомогу.",
|
||||
"log_link_to_failed_log": "Не вдалося завершити операцію '{desc}'. Будь ласка, надайте повний журнал цієї операції, <a href=\"#/tools/logs/{name}\"> натиснувши тут </a>, щоб отримати допомогу.",
|
||||
"log_help_to_get_log": "Щоб переглянути журнал операції '{desc}', використовуйте команду 'yunohost log show {name} {name}'.",
|
||||
"log_link_to_log": "Повний журнал цієї операції: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\"> {desc} </a>'",
|
||||
"log_corrupted_md_file": "Файл метаданих YAML, пов'язаний з журналами, пошкоджений: '{md_file} Помилка: {error}'",
|
||||
"iptables_unavailable": "Ви не можете грати з iptables тут. Ви перебуваєте або в контейнері, або ваше ядро не підтримує його.",
|
||||
"ip6tables_unavailable": "Ви не можете грати з ip6tables тут. Ви перебуваєте або в контейнері, або ваше ядро не підтримує його.",
|
||||
"invalid_regex": "Невірний regex: '{regex}'",
|
||||
"installation_complete": "установка завершена",
|
||||
"hook_name_unknown": "Невідоме ім'я хука '{name}'",
|
||||
"hook_list_by_invalid": "Це властивість не може бути використано для перерахування хуков",
|
||||
"hook_json_return_error": "Не вдалося розпізнати повернення з хука {шлях}. Помилка: {msg}. Необроблений контент: {raw_content}.",
|
||||
"hook_exec_not_terminated": "Скрипт не завершився належним чином: {шлях}",
|
||||
"hook_exec_failed": "Не вдалося запустити скрипт: {path}",
|
||||
"group_user_not_in_group": "Користувач {user} не входить в групу {group}",
|
||||
"group_user_already_in_group": "Користувач {user} вже в групі {group}",
|
||||
"group_update_failed": "Не вдалося оновити групу '{group}': {error}",
|
||||
"group_updated": "Група '{group}' оновлена",
|
||||
"group_unknown": "Група '{group}' невідома.",
|
||||
"group_deletion_failed": "Не вдалося видалити групу '{group}': {error}",
|
||||
"group_deleted": "Група '{group}' вилучена",
|
||||
"group_cannot_be_deleted": "Група {group} не може бути видалена вручну.",
|
||||
"group_cannot_edit_primary_group": "Група '{group}' не може бути відредаговано вручну. Це основна група, призначена тільки для одного конкретного користувача.",
|
||||
"group_cannot_edit_visitors": "Група 'visitors' не може бути відредаговано вручну. Це спеціальна група, що представляє анонімних відвідувачів.",
|
||||
"group_cannot_edit_all_users": "Група 'all_users' не може бути відредаговано вручну. Це спеціальна група, призначена для всіх користувачів, зареєстрованих в YunoHost.",
|
||||
"group_creation_failed": "Не вдалося створити групу \"{group} ': {error}",
|
||||
"group_created": "Група '{group}' створена",
|
||||
"group_already_exist_on_system_but_removing_it": "Група {group} вже існує в групах системи, але YunoHost видалить її...",
|
||||
"group_already_exist_on_system": "Група {group} вже існує в групах системи",
|
||||
"group_already_exist": "Група {group} вже існує",
|
||||
"good_practices_about_user_password": "Зараз ви маєте визначити новий пароль користувача. Пароль повинен складатися не менше ніж з 8 символів, але хорошою практикою є використання більш довгого пароля (тобто парольної фрази) і/або використання різних символів (заголовних, малих, цифр і спеціальних символів).",
|
||||
"good_practices_about_admin_password": "Зараз ви збираєтеся поставити новий пароль адміністратора. Пароль повинен складатися не менше ніж з 8 символів, але хорошою практикою є використання більш довгого пароля (тобто парольної фрази) і/або використання різних символів (прописних, малих, цифр і спеціальних символів).",
|
||||
"global_settings_unknown_type": "Несподівана ситуація, параметр {setting} має тип {unknown_type}, але це не тип, підтримуваний системою.",
|
||||
"global_settings_setting_backup_compress_tar_archives": "При створенні нових резервних копій стискати архіви (.tar.gz) замість незжатих архівів (.tar). NB: включення цієї опції означає створення більш легких архівів резервних копій, але початкова процедура резервного копіювання буде значно довше і важче для CPU.",
|
||||
"global_settings_setting_security_webadmin_allowlist": "IP-адреси, яким дозволений доступ до веб-адміну. Через кому.",
|
||||
"global_settings_setting_security_webadmin_allowlist_enabled": "Дозволити доступ до веб-адміну тільки деяким IP-адресами.",
|
||||
"global_settings_setting_smtp_relay_password": "Пароль хоста SMTP-ретрансляції",
|
||||
"global_settings_setting_smtp_relay_user": "Обліковий запис користувача SMTP-реле",
|
||||
"global_settings_setting_smtp_relay_port": "Порт SMTP-реле",
|
||||
"global_settings_setting_smtp_relay_host": "SMTP релейний хост, який буде використовуватися для відправки пошти замість цього примірника yunohost. Корисно, якщо ви знаходитеся в одній із цих ситуацій: ваш 25 порт заблокований вашим провайдером або VPS провайдером, у вас є житловий IP в списку DUHL, ви не можете налаштувати зворотний DNS або цей сервер не доступний безпосередньо в інтернеті і ви хочете використовувати інший сервер для відправки пошти.",
|
||||
"global_settings_setting_smtp_allow_ipv6": "Дозволити використання IPv6 для отримання і відправки пошти",
|
||||
"global_settings_setting_ssowat_panel_overlay_enabled": "Включити накладення панелі SSOwat",
|
||||
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Дозволити використання (застарілого) ключа DSA для конфігурації демона SSH",
|
||||
"global_settings_unknown_setting_from_settings_file": "Невідомий ключ в настройках: '{setting_key}', відкиньте його і збережіть в /etc/yunohost/settings-unknown.json",
|
||||
"global_settings_setting_security_ssh_port": "SSH-порт",
|
||||
"global_settings_setting_security_postfix_compatibility": "Компроміс між сумісністю і безпекою для сервера Postfix. Впливає на шифри (і інші аспекти, пов'язані з безпекою)",
|
||||
"global_settings_setting_security_ssh_compatibility": "Сумісність і співвідношення безпеки для SSH-сервера. Впливає на шифри (і інші аспекти, пов'язані з безпекою)",
|
||||
"global_settings_setting_security_password_user_strength": "Надійність пароля користувача",
|
||||
"global_settings_setting_security_password_admin_strength": "Надійність пароля адміністратора",
|
||||
"global_settings_setting_security_nginx_compatibility": "Компроміс між сумісністю і безпекою для веб-сервера NGINX. Впливає на шифри (і інші аспекти, пов'язані з безпекою)",
|
||||
"global_settings_setting_pop3_enabled": "Включити протокол POP3 для поштового сервера.",
|
||||
"global_settings_reset_success": "Попередні настройки тепер збережені в {шлях}.",
|
||||
"global_settings_key_doesnt_exists": "Ключ '{settings_key}' не існує в глобальних налаштуваннях, ви можете побачити всі доступні ключі, виконавши команду 'yunohost settings list'.",
|
||||
"global_settings_cant_write_settings": "Неможливо зберегти файл настройок, причина: {причина}",
|
||||
"global_settings_cant_serialize_settings": "Не вдалося серіалізовать дані налаштувань, причина: {причина}",
|
||||
"global_settings_cant_open_settings": "Не вдалося відкрити файл настройок, причина: {причина}",
|
||||
"global_settings_bad_type_for_setting": "Поганий тип для настройки {setting}, отриманий {received_type}, очікується {expected_type}",
|
||||
"global_settings_bad_choice_for_enum": "Поганий вибір для настройки {setting}, отримано '{choice}', але доступні наступні варіанти: {available_choices}.",
|
||||
"firewall_rules_cmd_failed": "Деякі команди правил брандмауера не спрацювали. Більш детальна інформація в журналі.",
|
||||
"firewall_reloaded": "брандмауер перезавантажений",
|
||||
"firewall_reload_failed": "Не вдалося перезавантажити брандмауер",
|
||||
"file_does_not_exist": "Файл {шлях} не існує.",
|
||||
"field_invalid": "Неприпустиме поле '{}'",
|
||||
"experimental_feature": "Попередження: Ця функція є експериментальною і не вважається стабільною, ви не повинні використовувати її, якщо не знаєте, що робите.",
|
||||
"extracting": "Витяг...",
|
||||
"dyndns_unavailable": "Домен '{domain}' недоступний.",
|
||||
"dyndns_domain_not_provided": "DynDNS провайдер {provider} не може надати домен {domain}.",
|
||||
"dyndns_registration_failed": "Не вдалося зареєструвати домен DynDNS: {error}.",
|
||||
"dyndns_registered": "Домен DynDNS зареєстрований",
|
||||
"dyndns_provider_unreachable": "Неможливо зв'язатися з провайдером DynDNS {provider}: або ваш YunoHost неправильно підключений до інтернету, або сервер dynette не працює.",
|
||||
"dyndns_no_domain_registered": "Домен не зареєстрований в DynDNS",
|
||||
"dyndns_key_not_found": "DNS-ключ не знайдений для домену",
|
||||
"dyndns_key_generating": "Генерація DNS-ключа... Це може зайняти деякий час.",
|
||||
"dyndns_ip_updated": "Оновлення свій IP-адресу в DynDNS",
|
||||
"dyndns_ip_update_failed": "Не вдалося оновити IP-адреса в DynDNS",
|
||||
"dyndns_could_not_check_available": "Не вдалося перевірити наявність певної {домен} на {провайдера}.",
|
||||
"dyndns_could_not_check_provide": "Не вдалося перевірити, чи може {провайдер} надати {домен}.",
|
||||
"dpkg_lock_not_available": "Ця команда не може бути виконана прямо зараз, тому що інша програма, схоже, використовує блокування dpkg (системного менеджера пакетів).",
|
||||
"dpkg_is_broken": "Ви не можете зробити це прямо зараз, тому що dpkg/APT (системні менеджери пакетів), схоже, знаходяться в зламаному стані... Ви можете спробувати вирішити цю проблему, підключившись через SSH і виконавши `sudo apt install --fix-broken` і/або `sudo dpkg --configure -a`.",
|
||||
"downloading": "Завантаження…",
|
||||
"done": "Готово",
|
||||
"domains_available": "Доступні домени:",
|
||||
"domain_unknown": "невідомий домен",
|
||||
"domain_name_unknown": "Домен '{domain}' невідомий",
|
||||
"domain_uninstall_app_first": "Ці додатки все ще встановлені на вашому домені: {apps} ласка, видаліть їх за допомогою 'yunohost app remove the_app_id' або перемістити їх на інший домен за допомогою 'yunohost app change-url the_app_id', перш ніж приступити до видалення домену.",
|
||||
"domain_remove_confirm_apps_removal": "Видалення цього домену призведе до видалення цих додатків: {apps} Ви впевнені, що хочете це зробити? [{Відповіді}].",
|
||||
"domain_hostname_failed": "Неможливо встановити нове ім'я хоста. Це може викликати проблеми в подальшому (можливо, все буде в порядку).",
|
||||
"domain_exists": "Домен вже існує",
|
||||
"domain_dyndns_root_unknown": "Невідомий кореневої домен DynDNS",
|
||||
"domain_dyndns_already_subscribed": "Ви вже підписалися на домен DynDNS",
|
||||
"domain_dns_conf_is_just_a_recommendation": "Ця команда показує * рекомендовану * конфігурацію. Насправді вона не встановлює конфігурацію DNS для вас. Ви самі повинні налаштувати свою зону DNS у реєстратора відповідно до цих рекомендацій.",
|
||||
"domain_deletion_failed": "Неможливо видалити домен {domain}: {помилка}",
|
||||
"domain_deleted": "домен видалений",
|
||||
"domain_creation_failed": "Неможливо створити домен {domain}: {помилка}",
|
||||
"domain_created": "домен створений",
|
||||
"domain_cert_gen_failed": "Не вдалося згенерувати сертифікат",
|
||||
"domain_cannot_remove_main_add_new_one": "Ви не можете видалити '{domain}', так як це основний домен і ваш єдиний домен, вам потрібно спочатку додати інший домен за допомогою 'yunohost domain add <another-domain.com>', потім встановити його як основний домен за допомогою ' yunohost domain main-domain -n <another-domain.com> 'і потім ви можете видалити домен' {domain} 'за допомогою' yunohost domain remove {domain} ''.",
|
||||
"domain_cannot_add_xmpp_upload": "Ви не можете додавати домени, що починаються з 'xmpp-upload.'. Таке ім'я зарезервовано для функції XMPP upload, вбудованої в YunoHost.",
|
||||
"domain_cannot_remove_main": "Ви не можете видалити '{domain}', так як це основний домен, спочатку вам потрібно встановити інший домен в якості основного за допомогою 'yunohost domain main-domain -n <another-domain>'; ось список доменів-кандидатів: {other_domains}",
|
||||
"disk_space_not_sufficient_update": "Недостатньо місця на диску для поновлення цього додатка",
|
||||
"disk_space_not_sufficient_install": "Бракує місця на диску для установки цього додатка",
|
||||
"diagnosis_sshd_config_inconsistent_details": "Будь ласка, виконайте <cmd> yunohost settings set security.ssh.port -v YOUR_SSH_PORT </ cmd>, щоб визначити порт SSH, і перевірте <cmd> yunohost tools regen-conf ssh --dry-run --with-diff </ cmd »і« cmd> yunohost tools regen-conf ssh --force </ cmd>, щоб скинути ваш conf на рекомендований YunoHost.",
|
||||
"diagnosis_sshd_config_inconsistent": "Схоже, що порт SSH був вручну змінений в/etc/ssh/sshd_config. Починаючи з версії YunoHost 4.2, доступний новий глобальний параметр 'security.ssh.port', що дозволяє уникнути ручного редагування конфігурації.",
|
||||
"diagnosis_sshd_config_insecure": "Схоже, що конфігурація SSH була змінена вручну і є небезпечною, оскільки не містить директив 'AllowGroups' або 'AllowUsers' для обмеження доступу авторизованих користувачів.",
|
||||
"diagnosis_processes_killed_by_oom_reaper": "Деякі процеси були недавно вбито системою через брак пам'яті. Зазвичай це є симптомом нестачі пам'яті в системі або процесу, який з'їв дуже багато пам'яті. Зведення убитих процесів: {kills_summary}",
|
||||
"diagnosis_never_ran_yet": "Схоже, що цей сервер був налаштований недавно, і поки немає звіту про діагностику. Вам слід почати з повної діагностики, або з веб-адміністратора, або використовуючи 'yunohost diagnosis run' з командного рядка.",
|
||||
"diagnosis_unknown_categories": "Наступні категорії невідомі: {categories}",
|
||||
"diagnosis_http_nginx_conf_not_up_to_date_details": "Щоб виправити ситуацію, перевірте різницю за допомогою командного рядка, використовуючи <cmd> yunohost tools regen-conf nginx --dry-run --with-diff </ cmd>, і якщо все в порядку, застосуйте зміни за допомогою <cmd> yunohost tools regen-conf nginx --force </ cmd>.",
|
||||
"diagnosis_http_nginx_conf_not_up_to_date": "Схоже, що конфігурація nginx цього домену була змінена вручну, що не дозволяє YunoHost визначити, чи доступний він по HTTP.",
|
||||
"diagnosis_http_partially_unreachable": "Домен {domain} здається недоступним по HTTP ззовні локальної мережі в IPv {failed}, хоча він працює в IPv {passed}.",
|
||||
"diagnosis_http_unreachable": "Домен {domain} здається недоступним через HTTP ззовні локальної мережі.",
|
||||
"diagnosis_http_bad_status_code": "Схоже, що замість вашого сервера відповіла інша машина (можливо, ваш маршрутизатор). <br> 1. Найбільш поширеною причиною цієї проблеми є те, що порт 80 (і 443) <a href='https://yunohost.org/isp_box_config'> неправильно перенаправлений на ваш сервер </a>. <br> 2. На більш складних установках: переконайтеся, що немає брандмауера або зворотного проксі.",
|
||||
"diagnosis_http_connection_error": "Помилка підключення: не вдалося підключитися до запитуваного домену, швидше за все, він недоступний.",
|
||||
"diagnosis_http_timeout": "При спробі зв'язатися з вашим сервером ззовні стався тайм-аут. Він здається недоступним. <br> 1. Найбільш поширеною причиною цієї проблеми є те, що порт 80 (і 443) <a href='https://yunohost.org/isp_box_config'> неправильно перенаправлений на ваш сервер </a>. <br> 2. Ви також повинні переконатися, що служба nginx запущена <br> 3. На більш складних установках: переконайтеся, що немає брандмауера або зворотного проксі.",
|
||||
"diagnosis_http_ok": "Домен {domain} доступний по HTTP ззовні локальної мережі.",
|
||||
"diagnosis_http_localdomain": "Домен {domain} з доменом .local TLD не може бути доступний ззовні локальної мережі.",
|
||||
"diagnosis_http_could_not_diagnose_details": "Помилка: {error}.",
|
||||
"diagnosis_http_could_not_diagnose": "Не вдалося діагностувати досяжність доменів ззовні в IPv {ipversion}.",
|
||||
"diagnosis_http_hairpinning_issue_details": "Можливо, це пов'язано з блоком/маршрутизатором вашого інтернет-провайдера. В результаті, люди ззовні вашої локальної мережі зможуть отримати доступ до вашого сервера, як і очікувалося, але не люди зсередини локальної мережі (як ви, ймовірно?) При використанні доменного імені або глобального IP. Можливо, ви зможете поліпшити ситуацію, глянувши на <a href='https://yunohost.org/dns_local_network'> https://yunohost.org/dns_local_network </a>.",
|
||||
"diagnosis_http_hairpinning_issue": "Схоже, що у вашій локальній мережі не включена проброска.",
|
||||
"diagnosis_ports_forwarding_tip": "Щоб вирішити цю проблему, вам, швидше за все, потрібно налаштувати кидок портів на вашому інтернет-маршрутизатор, як описано в <a href='https://yunohost.org/isp_box_config'> https://yunohost.org/isp_box_config</ a>.",
|
||||
"diagnosis_ports_needed_by": "Відкриття цього порту необхідно для функцій {категорії} (служба {сервіс}).",
|
||||
"diagnosis_ports_ok": "Порт {port} доступний ззовні.",
|
||||
"diagnosis_ports_partially_unreachable": "Порт {port} не доступний ззовні в IPv {failed}.",
|
||||
"diagnosis_ports_unreachable": "Порт {port} недоступний ззовні.",
|
||||
"diagnosis_ports_could_not_diagnose_details": "Помилка: {error}",
|
||||
"diagnosis_ports_could_not_diagnose": "Не вдалося діагностувати досяжність портів ззовні в IPv {ipversion}.",
|
||||
"diagnosis_description_regenconf": "Конфігурації системи",
|
||||
"diagnosis_description_mail": "Електронна пошта",
|
||||
"diagnosis_description_ports": "виявлення портів",
|
||||
"diagnosis_description_systemresources": "Системні ресурси",
|
||||
"diagnosis_description_services": "Перевірка стану служб",
|
||||
"diagnosis_description_dnsrecords": "записи DNS",
|
||||
"diagnosis_description_ip": "Інтернет-з'єднання",
|
||||
"diagnosis_description_basesystem": "Базова система",
|
||||
"diagnosis_security_vulnerable_to_meltdown_details": "Щоб виправити це, вам слід оновити систему і перезавантажитися, щоб завантажити нове ядро linux (або звернутися до вашого серверного провайдеру, якщо це не спрацює). Додаткову інформацію див. На сайті https://meltdownattack.com/.",
|
||||
"diagnosis_security_vulnerable_to_meltdown": "Схоже, що ви уразливі до критичної уразливості безпеки Meltdown.",
|
||||
"diagnosis_rootfstotalspace_critical": "Коренева файлова система має тільки {простір}, що вельми тривожно! Швидше за все, дисковий простір закінчиться дуже швидко! Рекомендується мати не менше 16 ГБ для кореневої файлової системи.",
|
||||
"diagnosis_rootfstotalspace_warning": "Коренева файлова система має тільки {простір}. Це може бути нормально, але будьте обережні, тому що в кінцевому підсумку дисковий простір може швидко закінчитися... Рекомендується мати не менше 16 ГБ для кореневої файлової системи.",
|
||||
"diagnosis_regenconf_manually_modified_details": "Це можливо нормально, якщо ви знаєте, що робите! YunoHost перестане оновлювати цей файл автоматично... Але врахуйте, що поновлення YunoHost можуть містити важливі рекомендовані зміни. Якщо ви хочете, ви можете перевірити відмінності за допомогою команди <cmd> yunohost tools regen-conf {category} --dry-run --with-diff </ cmd> і примусово повернути рекомендовану конфігурацію за допомогою <cmd> yunohost tools regen- conf {category} --force </ cmd>.",
|
||||
"diagnosis_regenconf_manually_modified": "Конфігураційний файл <code> {file} </ code>, схоже, був змінений вручну.",
|
||||
"diagnosis_regenconf_allgood": "Всі конфігураційні файли відповідають рекомендованої конфігурації!",
|
||||
"diagnosis_mail_queue_too_big": "Занадто багато відкладених листів в поштовій черзі ({nb_pending} emails)",
|
||||
"diagnosis_mail_queue_unavailable_details": "Помилка: {error}",
|
||||
"diagnosis_mail_queue_unavailable": "Неможливо дізнатися кількість очікують листів в черзі",
|
||||
"diagnosis_mail_queue_ok": "{nb_pending} відкладені листи в поштових чергах",
|
||||
"diagnosis_mail_blacklist_website": "Після визначення причини, по якій ви потрапили в чорний список, і її усунення, ви можете попросити видалити ваш IP або домен на {blacklist_website}.",
|
||||
"diagnosis_mail_blacklist_reason": "Причина внесення в чорний список: {причина}",
|
||||
"diagnosis_mail_blacklist_listed_by": "Ваш IP або домен <code> {item} </ code> знаходиться в чорному списку {blacklist_name}.",
|
||||
"diagnosis_mail_blacklist_ok": "IP-адреси і домени, які використовуються цим сервером, не внесені в чорний список",
|
||||
"diagnosis_mail_fcrdns_different_from_ehlo_domain_details": "Поточний зворотний DNS: <code> {rdns_domain} </ code> <br> Очікуване значення: <code> {ehlo_domain} </ code>.",
|
||||
"diagnosis_mail_fcrdns_different_from_ehlo_domain": "Зворотний DNS неправильно налаштований в IPv {ipversion}. Деякі електронні листи можуть бути не доставлені або можуть бути відзначені як спам.",
|
||||
"diagnosis_mail_fcrdns_nok_alternatives_6": "Деякі провайдери не дозволяють вам налаштувати зворотний DNS (або їх функція може бути зламана...). Якщо ваш зворотний DNS правильно налаштований для IPv4, ви можете спробувати відключити використання IPv6 при відправці листів, виконавши команду <cmd> yunohost settings set smtp.allow_ipv6 -v off </ cmd>. Примітка: останнє рішення означає, що ви не зможете відправляти або отримувати електронну пошту з нечисленних серверів, що використовують тільки IPv6.",
|
||||
"diagnosis_mail_fcrdns_nok_alternatives_4": "Деякі провайдери не дозволять вам налаштувати зворотний DNS (або їх функція може бути зламана...). Якщо ви відчуваєте проблеми з-за цього, розгляньте наступні рішення: <br> - Деякі провайдери надають альтернативу <a href='https://yunohost.org/#/email_configure_relay'> використання ретранслятора поштового сервера </a>, хоча це має на увазі, що ретранслятор зможе шпигувати за вашим поштовим трафіком. <br> - Альтернативою для захисту конфіденційності є використання VPN * з виділеним публічним IP * для обходу подібних обмежень. Дивіться <a href='https://yunohost.org/#/vpn_advantage'> https://yunohost.org/#/vpn_advantage </a> <br> - Або можна <a href = 'https://yunohost.org/#/isp '> переключитися на іншого провайдера </a>.",
|
||||
"diagnosis_mail_fcrdns_nok_details": "Спочатку спробуйте налаштувати зворотний DNS з <code> {ehlo_domain} </ code> в інтерфейсі вашого інтернет-маршрутизатора або в інтерфейсі вашого хостинг-провайдера. (Деякі хостинг-провайдери можуть вимагати, щоб ви відправили їм тікет підтримки для цього).",
|
||||
"diagnosis_mail_fcrdns_dns_missing": "У IPv {ipversion} не визначений зворотний DNS. Деякі листи можуть не доставлятися або позначатися як спам.",
|
||||
"diagnosis_mail_fcrdns_ok": "Ваш зворотний DNS налаштований правильно!",
|
||||
"diagnosis_mail_ehlo_could_not_diagnose_details": "Помилка: {error}.",
|
||||
"diagnosis_mail_ehlo_could_not_diagnose": "Не вдалося діагностувати наявність певної поштовий сервер postfix ззовні в IPv {ipversion}.",
|
||||
"diagnosis_mail_ehlo_wrong_details": "EHLO, отриманий віддаленим діагностичним центром в IPv {ipversion}, відрізняється від домену вашого сервера. <br> Отриманий EHLO: <code> {wrong_ehlo} </ code> <br> Очікуваний: <code> {right_ehlo} </ code> < br> найпоширенішою причиною цієї проблеми є те, що порт 25 <a href='https://yunohost.org/isp_box_config'> неправильно перенаправлений на ваш сервер </a>. Крім того, переконайтеся, що в роботу сервера не втручається брандмауер або зворотний проксі-сервер.",
|
||||
"diagnosis_mail_ehlo_wrong": "Інший поштовий SMTP-сервер відповідає на IPv {ipversion}. Ваш сервер, ймовірно, не зможе отримувати електронну пошту.",
|
||||
"diagnosis_mail_ehlo_bad_answer_details": "Це може бути викликано тим, що замість вашого сервера відповідає інша машина.",
|
||||
"diagnosis_mail_ehlo_bad_answer": "Ні-SMTP служба відповідає на порту 25 на IPv {ipversion}.",
|
||||
"diagnosis_mail_ehlo_unreachable_details": "Не вдалося відкрити з'єднання по порту 25 з вашим сервером на IPv {ipversion}. Він здається недоступним. <br> 1. Найбільш поширеною причиною цієї проблеми є те, що порт 25 <a href='https://yunohost.org/isp_box_config'> неправильно перенаправлений на ваш сервер </a>. <br> 2. Ви також повинні переконатися, що служба postfix запущена. <br> 3. На більш складних установках: переконайтеся, що немає брандмауера або зворотного проксі.",
|
||||
"diagnosis_mail_ehlo_unreachable": "Поштовий сервер SMTP недоступний ззовні по IPv {ipversion}. Він не зможе отримувати повідомлення електронної пошти.",
|
||||
"diagnosis_mail_ehlo_ok": "Поштовий сервер SMTP доступний ззовні і тому може отримувати електронну пошту!",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn": "Деякі провайдери не дозволять вам розблокувати вихідний порт 25, тому що вони не піклуються про Net Neutrality. <br> - Деякі з них пропонують альтернативу <a href='https://yunohost.org/#/email_configure_relay'> використання ретранслятора поштового сервера </a>, хоча це має на увазі, що ретранслятор зможе шпигувати за вашим поштовим трафіком. <br> - Альтернативою для захисту конфіденційності є використання VPN * з виділеним публічним IP * для обходу такого роду обмежень. Дивіться <a href='https://yunohost.org/#/vpn_advantage'> https://yunohost.org/#/vpn_advantage </a> <br> - Ви також можете розглянути можливість переходу на <a href = ' https://yunohost.org/#/isp'>более дружнього до мережевого нейтралітету провайдера </a>.",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_details": "Спочатку спробуйте розблокувати вихідний порт 25 в інтерфейсі вашого інтернет-маршрутизатора або в інтерфейсі вашого хостинг-провайдера. (Деякі хостинг-провайдери можуть вимагати, щоб ви відправили їм заявку в службу підтримки).",
|
||||
"diagnosis_mail_outgoing_port_25_blocked": "Поштовий сервер SMTP не може відправляти електронні листи на інші сервери, оскільки вихідний порт 25 заблокований в IPv {ipversion}.",
|
||||
"app_manifest_install_ask_path": "Оберіть шлях URL (після домену), за яким має бути встановлено цей застосунок",
|
||||
"yunohost_postinstall_end_tip": "Постінсталляція завершена! Щоб завершити установку, будь ласка, розгляньте наступні варіанти: - додавання першого користувача через розділ 'Користувачі' веб-адміністратора (або 'yunohost user create <username>' в командному рядку); - діагностику можливих проблем через розділ 'Діагностика' веб-адміністратора (або 'yunohost diagnosis run' в командному рядку); - читання розділів 'Завершення установки' і 'Знайомство з YunoHost' в документації адміністратора: https://yunohost.org/admindoc.",
|
||||
"yunohost_not_installed": "YunoHost встановлений неправильно. Будь ласка, запустіть 'yunohost tools postinstall'.",
|
||||
"yunohost_installing": "Установлення YunoHost...",
|
||||
"yunohost_configured": "YunoHost вже налаштований",
|
||||
"yunohost_already_installed": "YunoHost вже встановлено",
|
||||
"user_updated": "Інформація про користувача змінена",
|
||||
"user_update_failed": "Не вдалося оновити користувача {user}: {error}",
|
||||
"user_unknown": "Невідомий користувач: {user}",
|
||||
"user_home_creation_failed": "Не вдалося створити домашню папку для користувача",
|
||||
"user_deletion_failed": "Не вдалося видалити користувача {user}: {error}",
|
||||
"user_deleted": "користувача видалено",
|
||||
"user_creation_failed": "Не вдалося створити користувача {user}: {помилка}",
|
||||
"user_created": "Аккаунт було створено",
|
||||
"user_already_exists": "Користувач '{user}' вже існує",
|
||||
"upnp_port_open_failed": "Не вдалося відкрити порт через UPnP",
|
||||
"upnp_enabled": "UPnP включено",
|
||||
"upnp_disabled": "UPnP вимкнено",
|
||||
"upnp_dev_not_found": "UPnP-пристрій, не знайдено",
|
||||
"upgrading_packages": "Оновлення пакетів...",
|
||||
"upgrade_complete": "оновлення завершено",
|
||||
"updating_apt_cache": "Вибірка доступних оновлень для системних пакетів...",
|
||||
"update_apt_cache_warning": "Щось пішло не так при оновленні кеша APT (менеджера пакунків Debian). Ось дамп рядків sources.list, який може допомогти визначити проблемні рядки: {sourceslist}",
|
||||
"update_apt_cache_failed": "Неможливо оновити кеш APT (менеджер пакетів Debian). Ось дамп рядків sources.list, який може допомогти визначити проблемні рядки: {sourceslist}",
|
||||
"unrestore_app": "{App} не буде поновлено",
|
||||
"unlimit": "немає квоти",
|
||||
"unknown_main_domain_path": "Невідомий домен або шлях для '{app}'. Вам необхідно вказати домен і шлях, щоб мати можливість вказати URL для дозволу.",
|
||||
"unexpected_error": "Щось пішло не так: {error}",
|
||||
"unbackup_app": "{App} НЕ буде збережений",
|
||||
"tools_upgrade_special_packages_completed": "Оновлення пакета YunoHost завершено. Натисніть [Enter] для повернення командного рядка",
|
||||
"tools_upgrade_special_packages_explanation": "Спеціальне оновлення триватиме у фоновому режимі. Будь ласка, не запускайте ніяких інших дій на вашому сервері протягом наступних ~ 10 хвилин (в залежності від швидкості обладнання). Після цього вам, можливо, доведеться заново увійти в веб-адмін. Журнал поновлення буде доступний в Інструменти → Журнал (в веб-адміном) або за допомогою 'yunohost log list' (з командного рядка).",
|
||||
"tools_upgrade_special_packages": "Тепер оновлюємо \"спеціальні\" (пов'язані з yunohost) пакети…",
|
||||
"tools_upgrade_regular_packages_failed": "Не вдалося оновити пакети: {packages_list}",
|
||||
"tools_upgrade_regular_packages": "Тепер оновлюємо \"звичайні\" (не пов'язані з yunohost) пакети…",
|
||||
"tools_upgrade_cant_unhold_critical_packages": "Не вдалося утримати критичні пакети…",
|
||||
"tools_upgrade_cant_hold_critical_packages": "Не вдалося утримати критичні пакети…",
|
||||
"tools_upgrade_cant_both": "Неможливо оновити систему і програми одночасно",
|
||||
"tools_upgrade_at_least_one": "Будь ласка, вкажіть 'apps', або 'system'.",
|
||||
"this_action_broke_dpkg": "Ця дія порушило dpkg/APT (системні менеджери пакетів)... Ви можете спробувати вирішити цю проблему, підключившись по SSH і запустивши `sudo apt install --fix-broken` і/або` sudo dpkg --configure -a`.",
|
||||
"system_username_exists": "Ім'я користувача вже існує в списку користувачів системи",
|
||||
"system_upgraded": "система оновлена",
|
||||
"ssowat_conf_updated": "Конфігурація SSOwat оновлена",
|
||||
"ssowat_conf_generated": "Регенерувати конфігурація SSOwat",
|
||||
"show_tile_cant_be_enabled_for_regex": "Ви не можете включити 'show_tile' прямо зараз, тому що URL для дозволу '{permission}' являє собою регекс",
|
||||
"show_tile_cant_be_enabled_for_url_not_defined": "Ви не можете включити 'show_tile' прямо зараз, тому що спочатку ви повинні визначити URL для дозволу '{permission}'",
|
||||
"service_unknown": "Невідома служба '{service}'",
|
||||
"service_stopped": "Служба '{service}' зупинена",
|
||||
"service_stop_failed": "Неможливо зупинити службу '{service}' Недавні журнали служб: {logs}",
|
||||
"service_started": "Служба '{service}' запущена",
|
||||
"service_start_failed": "Не вдалося запустити службу '{service}' Recent service logs: {logs}",
|
||||
"diagnosis_mail_outgoing_port_25_ok": "Поштовий сервер SMTP може відправляти електронні листи (вихідний порт 25 не заблокований).",
|
||||
"diagnosis_swap_tip": "Будь ласка, будьте обережні і знайте, що якщо сервер розміщує своп на SD-карті або SSD-накопичувачі, це може різко скоротити термін служби устройства`.",
|
||||
"diagnosis_swap_ok": "Система має {усього} свопу!",
|
||||
"diagnosis_swap_notsomuch": "Система має тільки {усього} свопу. Щоб уникнути ситуацій, коли в системі закінчується пам'ять, слід передбачити наявність не менше {рекомендованого} обсягу підкачки.",
|
||||
"diagnosis_swap_none": "В системі повністю відсутній своп. Ви повинні розглянути можливість додавання принаймні {рекомендованого} обсягу підкачки, щоб уникнути ситуацій, коли системі не вистачає пам'яті.",
|
||||
"diagnosis_ram_ok": "Система все ще має {доступно} ({доступний_процент}%) оперативної пам'яті з {усього}.",
|
||||
"diagnosis_ram_low": "У системі є {доступно} ({доступний_процент}%) оперативної пам'яті (з {усього}). Будьте уважні.",
|
||||
"diagnosis_ram_verylow": "Система має тільки {доступне} ({доступний_процент}%) оперативної пам'яті! (З {усього})",
|
||||
"diagnosis_diskusage_ok": "У сховищі <code> {mountpoint} </ code> (на пристрої <code> {device} </ code>) залишилося {free} ({free_percent}%) вільного місця (з {total})!",
|
||||
"diagnosis_diskusage_low": "Сховище <code> {mountpoint} </ code> (на пристрої <code> {device} </ code>) має тільки {free} ({free_percent}%) вільного місця (з {total}). Будьте уважні.",
|
||||
"diagnosis_diskusage_verylow": "Сховище <code> {mountpoint} </ code> (на пристрої <code> {device} </ code>) має тільки {free} ({free_percent}%) вільного місця (з {total}). Вам дійсно варто подумати про очищення простору!",
|
||||
"diagnosis_services_bad_status_tip": "Ви можете спробувати <a href='#/services/{service}'> перезапустити службу </a>, а якщо це не допоможе, подивіться <a href='#/services/{service}'> журнали служби в webadmin </a> (з командного рядка це можна зробити за допомогою <cmd> yunohost service restart {service} </ cmd »і« cmd> yunohost service log {service} </ cmd>).",
|
||||
"diagnosis_services_bad_status": "Сервіс {service} знаходиться в {status} :(",
|
||||
"diagnosis_services_conf_broken": "Конфігурація порушена для служби {service}!",
|
||||
"diagnosis_services_running": "Служба {service} запущена!",
|
||||
"diagnosis_domain_expires_in": "Термін дії {домену} закінчується через {днів} днів.",
|
||||
"diagnosis_domain_expiration_error": "Термін дії деяких доменів закінчується ДУЖЕ СКОРО!",
|
||||
"diagnosis_domain_expiration_warning": "Термін дії деяких доменів закінчиться найближчим часом!",
|
||||
"diagnosis_domain_expiration_success": "Ваші домени зареєстровані і не збираються спливати найближчим часом.",
|
||||
"diagnosis_domain_expiration_not_found_details": "Інформація WHOIS для домену {domain} не містить інформації про термін дії?",
|
||||
"diagnosis_domain_not_found_details": "Домен {domain} не існує в базі даних WHOIS або термін його дії закінчився!",
|
||||
"diagnosis_domain_expiration_not_found": "Неможливо перевірити термін дії деяких доменів",
|
||||
"diagnosis_dns_specialusedomain": "Домен {domain} заснований на домені верхнього рівня спеціального призначення (TLD) і тому не очікується, що у нього будуть актуальні записи DNS.",
|
||||
"diagnosis_dns_try_dyndns_update_force": "Конфігурація DNS цього домену повинна автоматично управлятися YunoHost. Якщо це не так, ви можете спробувати примусово оновити її за допомогою команди <cmd> yunohost dyndns update --force </ cmd>.",
|
||||
"diagnosis_dns_point_to_doc": "Якщо вам потрібна допомога з налаштування DNS-записів, зверніться до документації на сайті <a href='https://yunohost.org/dns_config'> https://yunohost.org/dns_config </a>.",
|
||||
"diagnosis_dns_discrepancy": "Наступний запис DNS, схоже, не відповідає рекомендованої конфігурації: <br> Type: <code> {type} </ code> <br> Name: <code> {name} </ code> <br> Поточне значення: <code> {current} </ code> <br> Очікуване значення: <code> {value} </ code>",
|
||||
"diagnosis_dns_missing_record": "Згідно рекомендованої конфігурації DNS, ви повинні додати запис DNS з наступною інформацією. <br> Тип: <code> {type} </ code> <br> Name: <code> {name} </ code> <br> Value: < code> {value} </ code>.",
|
||||
"diagnosis_dns_bad_conf": "Деякі DNS-записи відсутні або невірні для домену {домен} (категорія {категорія})",
|
||||
"diagnosis_dns_good_conf": "DNS-записи правильно налаштовані для домену {домен} (категорія {категорія})",
|
||||
"diagnosis_ip_weird_resolvconf_details": "Файл <code> /etc/resolv.conf </ code> повинен бути симлінк на <code> /etc/resolvconf/run/resolv.conf </ code>, що вказує на <code> 127.0.0.1 </ code> (dnsmasq ). Якщо ви хочете вручну налаштувати DNS Резолвер, відредагуйте <code> /etc/resolv.dnsmasq.conf </ code>.",
|
||||
"diagnosis_ip_weird_resolvconf": "Дозвіл DNS, схоже, працює, але схоже, що ви використовуєте для користувача <code> /etc/resolv.conf </ code>.",
|
||||
"diagnosis_ip_broken_resolvconf": "Схоже, що дозвіл доменних імен на вашому сервері порушено, що пов'язано з тим, що <code> /etc/resolv.conf </ code> не вказує на <code> 127.0.0.1 </ code>.",
|
||||
"diagnosis_ip_broken_dnsresolution": "Дозвіл доменних імен, схоже, з якоїсь причини не працює... Брандмауер блокує DNS-запити?",
|
||||
"diagnosis_ip_dnsresolution_working": "Дозвіл доменних імен працює!",
|
||||
"diagnosis_ip_not_connected_at_all": "Здається, що сервер взагалі не підключений до Інтернету !?",
|
||||
"diagnosis_ip_local": "Локальний IP: <code> {local} </ code>.",
|
||||
"diagnosis_ip_global": "Глобальний IP: <code> {global} </ code>",
|
||||
"diagnosis_ip_no_ipv6_tip": "Наявність працюючого IPv6 не є обов'язковим для роботи вашого сервера, але це краще для здоров'я Інтернету в цілому. IPv6 зазвичай автоматично налаштовується системою або вашим провайдером, якщо він доступний. В іншому випадку вам, можливо, доведеться налаштувати деякі речі вручну, як пояснюється в документації тут: <a href='https://yunohost.org/#/ipv6'> https://yunohost.org/#/ipv6</ a>. Якщо ви не можете включити IPv6 або якщо це здається вам занадто технічним, ви також можете сміливо ігнорувати це попередження.",
|
||||
"diagnosis_ip_no_ipv6": "Сервер не має працюючого IPv6.",
|
||||
"diagnosis_ip_connected_ipv6": "Сервер підключений до Інтернету через IPv6!",
|
||||
"diagnosis_ip_no_ipv4": "Сервер не має працюючого IPv4.",
|
||||
"diagnosis_ip_connected_ipv4": "Сервер підключений до Інтернету через IPv4!",
|
||||
"diagnosis_no_cache": "Для категорії \"{категорія} 'ще немає кеша діагнозів.",
|
||||
"diagnosis_failed": "Не вдалося результат діагностики для категорії '{категорія}': {error}",
|
||||
"diagnosis_everything_ok": "Все виглядає добре для {категорії}!",
|
||||
"diagnosis_found_warnings": "Знайдено {попередження} пунктів, які можна поліпшити для {категорії}.",
|
||||
"diagnosis_found_errors_and_warnings": "Знайдено {помилки} істотний (і) питання (и) (і {попередження} попередження (я)), що відносяться до {категорії}!",
|
||||
"diagnosis_found_errors": "Знайдена {помилка} важлива проблема (і), пов'язана з {категорією}!",
|
||||
"diagnosis_ignored_issues": "(+ {Nb_ignored} проігнорована проблема (проблеми))",
|
||||
"diagnosis_cant_run_because_of_dep": "Неможливо запустити діагностику для {категорії}, поки є важливі проблеми, пов'язані з {глибиною}.",
|
||||
"diagnosis_cache_still_valid": "(Кеш все ще дійсний для діагностики {категорії}. Повторна діагностика поки не проводиться!)",
|
||||
"diagnosis_failed_for_category": "Не вдалося провести діагностику для категорії '{категорія}': {error}",
|
||||
"diagnosis_display_tip": "Щоб побачити знайдені проблеми, ви можете перейти в розділ Diagnosis в веб-адміном або виконати команду 'yunohost diagnosis show --issues --human-readable' з командного рядка.",
|
||||
"diagnosis_package_installed_from_sury_details": "Деякі пакети були ненавмисно встановлені з стороннього сховища під назвою Sury. Команда YunoHost поліпшила стратегію роботи з цими пакетами, але очікується, що в деяких системах, які встановили додатки PHP7.3 ще на Stretch, залишаться деякі невідповідності. Щоб виправити цю ситуацію, спробуйте виконати наступну команду: <cmd> {cmd_to_fix} </ cmd>.",
|
||||
"diagnosis_package_installed_from_sury": "Деякі системні пакети повинні бути знижені в статусі",
|
||||
"diagnosis_backports_in_sources_list": "Схоже, що apt (менеджер пакетів) налаштований на використання сховища backports. Якщо ви не знаєте, що робите, ми настійно не рекомендуємо встановлювати пакети з backports, тому що це може привести до нестабільності або конфліктів у вашій системі.",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "Ви використовуєте несумісні версії пакетів YunoHost... швидше за все, через невдалий або часткового оновлення.",
|
||||
"diagnosis_basesystem_ynh_main_version": "Сервер працює під управлінням YunoHost {main_version} ({repo})",
|
||||
"diagnosis_basesystem_ynh_single_version": "{Пакет} версія: {версія} ({repo})",
|
||||
"diagnosis_basesystem_kernel": "Сервер працює під управлінням ядра Linux {kernel_version}",
|
||||
"diagnosis_basesystem_host": "Сервер працює під управлінням Debian {debian_version}",
|
||||
"diagnosis_basesystem_hardware_model": "Модель сервера - {model}",
|
||||
"diagnosis_basesystem_hardware": "Архітектура апаратного забезпечення сервера - {virt} {arch}",
|
||||
"custom_app_url_required": "Ви повинні надати URL для оновлення вашого призначеного для користувача додатки {app}.",
|
||||
"confirm_app_install_thirdparty": "НЕБЕЗПЕЧНО! Ця програма не входить в каталог додатків YunoHost. Установлення сторонніх додатків може порушити цілісність і безпеку вашої системи. Вам не слід встановлювати його, якщо ви не знаєте, що робите. НІЯКОЇ ПІДТРИМКИ НЕ БУДЕ, якщо цей додаток не буде працювати або зламає вашу систему... Якщо ви все одно готові піти на такий ризик, введіть '{answers}'.",
|
||||
"confirm_app_install_danger": "НЕБЕЗПЕЧНО! Відомо, що це додаток все ще експериментальне (якщо не сказати, що воно явно не працює)! Вам не слід встановлювати його, якщо ви не знаєте, що робите. Ніякої підтримки не буде надано, якщо цей додаток не буде працювати або зламає вашу систему... Якщо ви все одно готові ризикнути, введіть '{answers}'.",
|
||||
"confirm_app_install_warning": "Попередження: Ця програма може працювати, але не дуже добре інтегровано в YunoHost. Деякі функції, такі як єдина реєстрація та резервне копіювання/відновлення, можуть бути недоступні. Все одно встановити? [{Відповіді}]. ",
|
||||
"certmanager_unable_to_parse_self_CA_name": "Не вдалося розібрати ім'я самоподпісивающегося центру (файл: {file})",
|
||||
"certmanager_self_ca_conf_file_not_found": "Не вдалося знайти файл конфігурації для самоподпісивающегося центру (файл: {file})",
|
||||
"certmanager_no_cert_file": "Не вдалося розпізнати файл сертифіката для домену {domain} (файл: {file})",
|
||||
"certmanager_hit_rate_limit": "Для цього набору доменів {domain} недавно було випущено дуже багато сертифікатів. Будь ласка, спробуйте ще раз пізніше. Див. Https://letsencrypt.org/docs/rate-limits/ для отримання більш докладної інформації.",
|
||||
"certmanager_warning_subdomain_dns_record": "Піддомен '{subdomain} \"не дозволяється на той же IP-адресу, що і' {domain} '. Деякі функції будуть недоступні, поки ви не виправите це і не перегенеріруете сертифікат.",
|
||||
"certmanager_domain_http_not_working": "Домен {domain}, схоже, не доступний через HTTP. Будь ласка, перевірте категорію 'Web' в діагностиці для отримання додаткової інформації. (Якщо ви знаєте, що робите, використовуйте '--no-checks', щоб відключити ці перевірки).",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "DNS-записи для домену '{domain}' відрізняються від IP цього сервера. Будь ласка, перевірте категорію 'DNS-записи' (основні) в діагностиці для отримання додаткової інформації. Якщо ви недавно змінили запис A, будь ласка, зачекайте, поки вона пошириться (деякі програми перевірки поширення DNS доступні в Інтернеті). (Якщо ви знаєте, що робите, використовуйте '--no-checks', щоб відключити ці перевірки).",
|
||||
"certmanager_domain_cert_not_selfsigned": "Сертифікат для домену {domain} не є самоподпісанного. Ви впевнені, що хочете замінити його? (Для цього використовуйте '--force').",
|
||||
"certmanager_domain_not_diagnosed_yet": "Поки немає результатів діагностики для домену {domain}. Будь ласка, повторно проведіть діагностику для категорій 'DNS-записи' і 'Web' в розділі діагностики, щоб перевірити, чи готовий домен до Let's Encrypt. (Або, якщо ви знаєте, що робите, використовуйте '--no-checks', щоб відключити ці перевірки).",
|
||||
"certmanager_certificate_fetching_or_enabling_failed": "Спроба використовувати новий сертифікат для {domain} не спрацювала...",
|
||||
"certmanager_cert_signing_failed": "Не вдалося підписати новий сертифікат",
|
||||
"certmanager_cert_renew_success": "Сертифікат Let's Encrypt оновлений для домену '{domain}'",
|
||||
"certmanager_cert_install_success_selfsigned": "Самоподпісанний сертифікат тепер встановлений для домену '{domain}'",
|
||||
"certmanager_cert_install_success": "Сертифікат Let's Encrypt тепер встановлений для домену '{domain}'",
|
||||
"certmanager_cannot_read_cert": "Щось не так сталося при спробі відкрити поточний сертифікат для домену {domain} (файл: {файл}), причина: {причина}",
|
||||
"certmanager_attempt_to_replace_valid_cert": "Ви намагаєтеся перезаписати хороший і дійсний сертифікат для домену {domain}! (Використовуйте --force для обходу)",
|
||||
"certmanager_attempt_to_renew_valid_cert": "Термін дії сертифіката для домену '{domain} \"не закінчується! (Ви можете використовувати --force, якщо знаєте, що робите)",
|
||||
"certmanager_attempt_to_renew_nonLE_cert": "Сертифікат для домену '{domain}' не випущено Let's Encrypt. Неможливо продовжити його автоматично!",
|
||||
"certmanager_acme_not_configured_for_domain": "Завдання ACME не може бути запущена для {domain} прямо зараз, тому що в його nginx conf відсутній відповідний фрагмент коду... Будь ласка, переконайтеся, що конфігурація nginx оновлена за допомогою `yunohost tools regen-conf nginx --dry-run - with-diff`.",
|
||||
"backup_with_no_restore_script_for_app": "{App} не має скрипта відновлення, ви не зможете автоматично відновити резервну копію цього додатка.",
|
||||
"backup_with_no_backup_script_for_app": "Додаток '{app}' не має скрипта резервного копіювання. Ігнорування.",
|
||||
"backup_unable_to_organize_files": "Неможливо використовувати швидкий метод для організації файлів в архіві",
|
||||
"backup_system_part_failed": "Не вдалося створити резервну копію системної частини '{part}'.",
|
||||
"backup_running_hooks": "Запуск гачків резервного копіювання...",
|
||||
"backup_permission": "Дозвіл на резервне копіювання для {app}",
|
||||
"backup_output_symlink_dir_broken": "Ваш архівний каталог '{path}' є непрацюючою симлінк. Можливо, ви забули перемонтувати або підключити носій, на який вона вказує.",
|
||||
"backup_output_directory_required": "Ви повинні вказати вихідний каталог для резервного копіювання",
|
||||
"backup_output_directory_not_empty": "Ви повинні вибрати порожній вихідний каталог",
|
||||
"backup_output_directory_forbidden": "Виберіть інший вихідний каталог. Резервні копії не можуть бути створені в підкаталогах/bin,/boot,/dev,/etc,/lib,/root,/run,/sbin,/sys,/usr,/var або /home/yunohost.backup/archives.",
|
||||
"backup_nothings_done": "нічого зберігати",
|
||||
"backup_no_uncompress_archive_dir": "Немає такого каталогу нестислого архіву",
|
||||
"backup_mount_archive_for_restore": "Підготовка архіву для відновлення...",
|
||||
"backup_method_tar_finished": "Створено архів резервного копіювання TAR",
|
||||
"backup_method_custom_finished": "Призначений для користувача метод резервного копіювання '{метод}' завершено",
|
||||
"backup_method_copy_finished": "Резервне копіювання завершено",
|
||||
"backup_hook_unknown": "Гачок резервного копіювання '{hook}' невідомий",
|
||||
"backup_deleted": "Резервна копія видалена",
|
||||
"backup_delete_error": "Не вдалося видалити '{path}'",
|
||||
"backup_custom_mount_error": "Призначений для користувача метод резервного копіювання не зміг пройти етап 'монтування'",
|
||||
"backup_custom_backup_error": "Призначений для користувача метод резервного копіювання не зміг пройти етап 'резервне копіювання'",
|
||||
"backup_csv_creation_failed": "Не вдалося створити CSV-файл, необхідний для відновлення",
|
||||
"backup_csv_addition_failed": "Не вдалося додати файли для резервного копіювання в CSV-файл",
|
||||
"backup_creation_failed": "Не вдалося створити архів резервного копіювання",
|
||||
"backup_create_size_estimation": "Архів буде містити близько {розмір} даних.",
|
||||
"backup_created": "Резервна копія створена",
|
||||
"backup_couldnt_bind": "Не вдалося зв'язати {src} з {dest}.",
|
||||
"backup_copying_to_organize_the_archive": "Копіювання {size} MB для організації архіву",
|
||||
"backup_cleaning_failed": "Не вдалося очистити тимчасову папку резервного копіювання",
|
||||
"backup_cant_mount_uncompress_archive": "Не вдалося змонтувати нестислий архів як захищений від запису",
|
||||
"backup_ask_for_copying_if_needed": "Чи хочете ви тимчасово виконати резервне копіювання з використанням {size} MB? (Цей спосіб використовується, оскільки деякі файли не можуть бути підготовлені більш ефективним методом).",
|
||||
"backup_archive_writing_error": "Не вдалося додати файли '{source}' (названі в архіві '{dest}') для резервного копіювання в стислий архів '{archive}'.",
|
||||
"backup_archive_system_part_not_available": "Системна частина '{part}' недоступна в цій резервної копії",
|
||||
"backup_archive_corrupted": "Схоже, що архів резервної копії \"{archive} 'пошкоджений: {error}",
|
||||
"backup_archive_cant_retrieve_info_json": "Не вдалося завантажити інформацію для архіву '{archive}'... info.json не може бути отриманий (або не є коректним json).",
|
||||
"backup_archive_open_failed": "Не вдалося відкрити архів резервних копій",
|
||||
"backup_archive_name_unknown": "Невідомий локальний архів резервного копіювання з ім'ям '{name}'",
|
||||
"backup_archive_name_exists": "Архів резервного копіювання з таким ім'ям вже існує.",
|
||||
"backup_archive_broken_link": "Не вдалося отримати доступ до архіву резервного копіювання (непрацююча посилання на {path})",
|
||||
"backup_archive_app_not_found": "Не вдалося знайти {app} в архіві резервного копіювання",
|
||||
"backup_applying_method_tar": "Створення резервного TAR-архіву...",
|
||||
"backup_applying_method_custom": "Виклик для користувача методу резервного копіювання '{метод}'...",
|
||||
"backup_applying_method_copy": "Копіювання всіх файлів в резервну копію...",
|
||||
"backup_app_failed": "Не вдалося створити резервну копію {app}",
|
||||
"backup_actually_backuping": "Створення резервного архіву з зібраних файлів...",
|
||||
"backup_abstract_method": "Цей метод резервного копіювання ще не реалізований",
|
||||
"ask_password": "пароль",
|
||||
"ask_new_path": "Новий шлях",
|
||||
"ask_new_domain": "новий домен",
|
||||
"ask_new_admin_password": "Новий адміністративний пароль",
|
||||
"ask_main_domain": "основний домен",
|
||||
"ask_lastname": "Прізвище",
|
||||
"ask_firstname": "ім'я",
|
||||
"ask_user_domain": "Домен для адреси електронної пошти користувача і облікового запису XMPP",
|
||||
"apps_catalog_update_success": "Каталог додатків був оновлений!",
|
||||
"apps_catalog_obsolete_cache": "Кеш каталогу додатків порожній або застарів.",
|
||||
"apps_catalog_failed_to_download": "Неможливо завантажити каталог додатків {apps_catalog}: {помилка}.",
|
||||
"apps_catalog_updating": "Оновлення каталогу додатків…",
|
||||
"apps_catalog_init_success": "Система каталогу додатків инициализирована!",
|
||||
"apps_already_up_to_date": "Всі додатки вже оновлені",
|
||||
"app_packaging_format_not_supported": "Ця програма не може бути встановлено, тому що формат його упаковки не підтримується вашою версією YunoHost. Можливо, вам слід оновити вашу систему.",
|
||||
"app_upgraded": "{App} оновлено",
|
||||
"app_upgrade_some_app_failed": "Деякі програми не можуть бути оновлені",
|
||||
"app_upgrade_script_failed": "Сталася помилка в сценарії оновлення програми",
|
||||
"app_upgrade_failed": "Не вдалося оновити {app}: {error}",
|
||||
"app_upgrade_app_name": "Зараз оновлюємо {app}...",
|
||||
"app_upgrade_several_apps": "Наступні додатки будуть оновлені: {apps}",
|
||||
"app_unsupported_remote_type": "Для додатка використовується непідтримуваний віддалений тип.",
|
||||
"app_unknown": "невідоме додаток",
|
||||
"app_start_restore": "Відновлення {app}...",
|
||||
"app_start_backup": "Збір файлів для резервного копіювання {app}...",
|
||||
"app_start_remove": "Видалення {app}...",
|
||||
"app_start_install": "Установлення {app}...",
|
||||
"app_sources_fetch_failed": "Не вдалося вихідні файли, URL коректний?",
|
||||
"app_restore_script_failed": "Сталася помилка всередині скрипта відновити оригінальну програму",
|
||||
"app_restore_failed": "Не вдалося відновити {app}: {error}",
|
||||
"app_remove_after_failed_install": "Видалення програми після збою установки...",
|
||||
"app_requirements_unmeet": "Вимоги не виконані для {app}, пакет {pkgname} ({version}) повинен бути {spec}.",
|
||||
"app_requirements_checking": "Перевірка необхідних пакетів для {app}...",
|
||||
"app_removed": "{App} видалено",
|
||||
"app_not_properly_removed": "{App} не було видалено належним чином",
|
||||
"app_not_installed": "Не вдалося знайти {app} в списку встановлених додатків: {all_apps}",
|
||||
"app_not_correctly_installed": "{App}, схоже, неправильно встановлено",
|
||||
"app_not_upgraded": "Додаток '{failed_app}' не вдалося оновити, і, як наслідок, оновлення таких програмах було скасовано: {apps}",
|
||||
"app_manifest_install_ask_is_public": "Чи повинно це додаток бути відкрито для анонімних відвідувачів?",
|
||||
"app_manifest_install_ask_admin": "Виберіть користувача-адміністратора для цього додатка",
|
||||
"app_manifest_install_ask_password": "Виберіть пароль адміністратора для цього додатка"
|
||||
}
|
||||
|
|
|
@ -226,7 +226,6 @@
|
|||
"service_description_fail2ban": "防止来自互联网的暴力攻击和其他类型的攻击",
|
||||
"service_description_dovecot": "允许电子邮件客户端访问/获取电子邮件(通过IMAP和POP3)",
|
||||
"service_description_dnsmasq": "处理域名解析(DNS)",
|
||||
"service_description_avahi-daemon": "允许您使用本地网络中的“ yunohost.local”访问服务器",
|
||||
"service_started": "服务 '{service}' 已启动",
|
||||
"service_start_failed": "无法启动服务 '{service}'\n\n最近的服务日志:{logs}",
|
||||
"service_reloaded_or_restarted": "服务'{service}'已重新加载或重新启动",
|
||||
|
|
|
@ -36,7 +36,7 @@ import urllib.parse
|
|||
import tempfile
|
||||
from collections import OrderedDict
|
||||
|
||||
from moulinette import msignals, m18n, msettings
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.core import MoulinetteError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.network import download_json
|
||||
|
@ -167,7 +167,8 @@ def app_info(app, full=False):
|
|||
"app_not_installed", app=app, all_apps=_get_all_installed_apps_id()
|
||||
)
|
||||
|
||||
local_manifest = _get_manifest_of_app(os.path.join(APPS_SETTING_PATH, app))
|
||||
setting_path = os.path.join(APPS_SETTING_PATH, app)
|
||||
local_manifest = _get_manifest_of_app(setting_path)
|
||||
permissions = user_permission_list(full=True, absolute_urls=True, apps=[app])[
|
||||
"permissions"
|
||||
]
|
||||
|
@ -186,6 +187,7 @@ def app_info(app, full=False):
|
|||
if not full:
|
||||
return ret
|
||||
|
||||
ret["setting_path"] = setting_path
|
||||
ret["manifest"] = local_manifest
|
||||
ret["manifest"]["arguments"] = _set_default_ask_questions(
|
||||
ret["manifest"].get("arguments", {})
|
||||
|
@ -196,11 +198,11 @@ def app_info(app, full=False):
|
|||
ret["from_catalog"] = _load_apps_catalog()["apps"].get(absolute_app_name, {})
|
||||
ret["upgradable"] = _app_upgradable(ret)
|
||||
ret["supports_change_url"] = os.path.exists(
|
||||
os.path.join(APPS_SETTING_PATH, app, "scripts", "change_url")
|
||||
os.path.join(setting_path, "scripts", "change_url")
|
||||
)
|
||||
ret["supports_backup_restore"] = os.path.exists(
|
||||
os.path.join(APPS_SETTING_PATH, app, "scripts", "backup")
|
||||
) and os.path.exists(os.path.join(APPS_SETTING_PATH, app, "scripts", "restore"))
|
||||
os.path.join(setting_path, "scripts", "backup")
|
||||
) and os.path.exists(os.path.join(setting_path, "scripts", "restore"))
|
||||
ret["supports_multi_instance"] = is_true(
|
||||
local_manifest.get("multi_instance", False)
|
||||
)
|
||||
|
@ -475,7 +477,7 @@ def app_change_url(operation_logger, app, domain, path):
|
|||
hook_callback("post_app_change_url", env=env_dict)
|
||||
|
||||
|
||||
def app_upgrade(app=[], url=None, file=None, force=False):
|
||||
def app_upgrade(app=[], url=None, file=None, force=False, no_safety_backup=False):
|
||||
"""
|
||||
Upgrade app
|
||||
|
||||
|
@ -483,6 +485,7 @@ def app_upgrade(app=[], url=None, file=None, force=False):
|
|||
file -- Folder or tarball for upgrade
|
||||
app -- App(s) to upgrade (default all)
|
||||
url -- Git url to fetch for upgrade
|
||||
no_safety_backup -- Disable the safety backup during upgrade
|
||||
|
||||
"""
|
||||
from packaging import version
|
||||
|
@ -591,6 +594,7 @@ def app_upgrade(app=[], url=None, file=None, force=False):
|
|||
env_dict["YNH_APP_UPGRADE_TYPE"] = upgrade_type
|
||||
env_dict["YNH_APP_MANIFEST_VERSION"] = str(app_new_version)
|
||||
env_dict["YNH_APP_CURRENT_VERSION"] = str(app_current_version)
|
||||
env_dict["NO_BACKUP_UPGRADE"] = "1" if no_safety_backup else "0"
|
||||
|
||||
# We'll check that the app didn't brutally edit some system configuration
|
||||
manually_modified_files_before_install = manually_modified_files()
|
||||
|
@ -620,7 +624,7 @@ def app_upgrade(app=[], url=None, file=None, force=False):
|
|||
m18n.n("app_upgrade_failed", app=app_instance_name, error=error)
|
||||
)
|
||||
failure_message_with_debug_instructions = operation_logger.error(error)
|
||||
if msettings.get("interface") != "api":
|
||||
if Moulinette.interface.type != "api":
|
||||
dump_app_log_extract_for_debugging(operation_logger)
|
||||
# Script got manually interrupted ... N.B. : KeyboardInterrupt does not inherit from Exception
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
|
@ -798,11 +802,11 @@ def app_install(
|
|||
def confirm_install(confirm):
|
||||
# Ignore if there's nothing for confirm (good quality app), if --force is used
|
||||
# or if request on the API (confirm already implemented on the API side)
|
||||
if confirm is None or force or msettings.get("interface") == "api":
|
||||
if confirm is None or force or Moulinette.interface.type == "api":
|
||||
return
|
||||
|
||||
if confirm in ["danger", "thirdparty"]:
|
||||
answer = msignals.prompt(
|
||||
answer = Moulinette.prompt(
|
||||
m18n.n("confirm_app_install_" + confirm, answers="Yes, I understand"),
|
||||
color="red",
|
||||
)
|
||||
|
@ -810,7 +814,7 @@ def app_install(
|
|||
raise YunohostError("aborting")
|
||||
|
||||
else:
|
||||
answer = msignals.prompt(
|
||||
answer = Moulinette.prompt(
|
||||
m18n.n("confirm_app_install_" + confirm, answers="Y/N"), color="yellow"
|
||||
)
|
||||
if answer.upper() != "Y":
|
||||
|
@ -858,7 +862,7 @@ def app_install(
|
|||
raise YunohostValidationError("disk_space_not_sufficient_install")
|
||||
|
||||
# Check ID
|
||||
if "id" not in manifest or "__" in manifest["id"]:
|
||||
if "id" not in manifest or "__" in manifest["id"] or "." in manifest["id"]:
|
||||
raise YunohostValidationError("app_id_invalid")
|
||||
|
||||
app_id = manifest["id"]
|
||||
|
@ -986,7 +990,7 @@ def app_install(
|
|||
error = m18n.n("app_install_script_failed")
|
||||
logger.error(m18n.n("app_install_failed", app=app_id, error=error))
|
||||
failure_message_with_debug_instructions = operation_logger.error(error)
|
||||
if msettings.get("interface") != "api":
|
||||
if Moulinette.interface.type != "api":
|
||||
dump_app_log_extract_for_debugging(operation_logger)
|
||||
# Script got manually interrupted ... N.B. : KeyboardInterrupt does not inherit from Exception
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
|
@ -1160,12 +1164,13 @@ def dump_app_log_extract_for_debugging(operation_logger):
|
|||
|
||||
|
||||
@is_unit_operation()
|
||||
def app_remove(operation_logger, app):
|
||||
def app_remove(operation_logger, app, purge=False):
|
||||
"""
|
||||
Remove app
|
||||
|
||||
Keyword argument:
|
||||
Keyword arguments:
|
||||
app -- App(s) to delete
|
||||
purge -- Remove with all app data
|
||||
|
||||
"""
|
||||
from yunohost.hook import hook_exec, hook_remove, hook_callback
|
||||
|
@ -1203,6 +1208,7 @@ def app_remove(operation_logger, app):
|
|||
env_dict["YNH_APP_INSTANCE_NAME"] = app
|
||||
env_dict["YNH_APP_INSTANCE_NUMBER"] = str(app_instance_nb)
|
||||
env_dict["YNH_APP_MANIFEST_VERSION"] = manifest.get("version", "?")
|
||||
env_dict["YNH_APP_PURGE"] = str(purge)
|
||||
operation_logger.extra.update({"env": env_dict})
|
||||
operation_logger.flush()
|
||||
|
||||
|
@ -2648,7 +2654,7 @@ class YunoHostArgumentFormatParser(object):
|
|||
)
|
||||
|
||||
try:
|
||||
question.value = msignals.prompt(
|
||||
question.value = Moulinette.prompt(
|
||||
text_for_user_input_in_cli, self.hide_user_input_in_prompt
|
||||
)
|
||||
except NotImplementedError:
|
||||
|
|
68
src/yunohost/authenticators/ldap_admin.py
Normal file
68
src/yunohost/authenticators/ldap_admin.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import logging
|
||||
import ldap
|
||||
import ldap.sasl
|
||||
import time
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.authentication import BaseAuthenticator
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
||||
logger = logging.getLogger("yunohost.authenticators.ldap_admin")
|
||||
|
||||
|
||||
class Authenticator(BaseAuthenticator):
|
||||
|
||||
name = "ldap_admin"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.uri = "ldap://localhost:389"
|
||||
self.basedn = "dc=yunohost,dc=org"
|
||||
self.admindn = "cn=admin,dc=yunohost,dc=org"
|
||||
|
||||
def _authenticate_credentials(self, credentials=None):
|
||||
|
||||
# TODO : change authentication format
|
||||
# to support another dn to support multi-admins
|
||||
|
||||
def _reconnect():
|
||||
con = ldap.ldapobject.ReconnectLDAPObject(
|
||||
self.uri, retry_max=10, retry_delay=0.5
|
||||
)
|
||||
con.simple_bind_s(self.admindn, credentials)
|
||||
return con
|
||||
|
||||
try:
|
||||
con = _reconnect()
|
||||
except ldap.INVALID_CREDENTIALS:
|
||||
raise YunohostError("invalid_password")
|
||||
except ldap.SERVER_DOWN:
|
||||
# ldap is down, attempt to restart it before really failing
|
||||
logger.warning(m18n.n("ldap_server_is_down_restart_it"))
|
||||
os.system("systemctl restart slapd")
|
||||
time.sleep(10) # waits 10 secondes so we are sure that slapd has restarted
|
||||
|
||||
try:
|
||||
con = _reconnect()
|
||||
except ldap.SERVER_DOWN:
|
||||
raise YunohostError("ldap_server_down")
|
||||
|
||||
# Check that we are indeed logged in with the expected identity
|
||||
try:
|
||||
# whoami_s return dn:..., then delete these 3 characters
|
||||
who = con.whoami_s()[3:]
|
||||
except Exception as e:
|
||||
logger.warning("Error during ldap authentication process: %s", e)
|
||||
raise
|
||||
else:
|
||||
if who != self.admindn:
|
||||
raise YunohostError(
|
||||
f"Not logged with the appropriate identity ? Found {who}, expected {self.admindn} !?",
|
||||
raw_msg=True,
|
||||
)
|
||||
finally:
|
||||
# Free the connection, we don't really need it to keep it open as the point is only to check authentication...
|
||||
if con:
|
||||
con.unbind_s()
|
|
@ -38,7 +38,7 @@ from collections import OrderedDict
|
|||
from functools import reduce
|
||||
from packaging import version
|
||||
|
||||
from moulinette import msignals, m18n, msettings
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.utils import filesystem
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, mkdir, write_to_yaml, read_yaml
|
||||
|
@ -1513,7 +1513,7 @@ class RestoreManager:
|
|||
m18n.n("app_restore_failed", app=app_instance_name, error=error)
|
||||
)
|
||||
failure_message_with_debug_instructions = operation_logger.error(error)
|
||||
if msettings.get("interface") != "api":
|
||||
if Moulinette.interface.type != "api":
|
||||
dump_app_log_extract_for_debugging(operation_logger)
|
||||
# Script got manually interrupted ... N.B. : KeyboardInterrupt does not inherit from Exception
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
|
@ -1844,7 +1844,7 @@ class BackupMethod(object):
|
|||
# Ask confirmation for copying
|
||||
if size > MB_ALLOWED_TO_ORGANIZE:
|
||||
try:
|
||||
i = msignals.prompt(
|
||||
i = Moulinette.prompt(
|
||||
m18n.n(
|
||||
"backup_ask_for_copying_if_needed",
|
||||
answers="y/N",
|
||||
|
@ -2348,7 +2348,7 @@ def backup_restore(name, system=[], apps=[], force=False):
|
|||
if not force:
|
||||
try:
|
||||
# Ask confirmation for restoring
|
||||
i = msignals.prompt(
|
||||
i = Moulinette.prompt(
|
||||
m18n.n("restore_confirm_yunohost_installed", answers="y/N")
|
||||
)
|
||||
except NotImplemented:
|
||||
|
@ -2422,7 +2422,7 @@ def backup_list(with_info=False, human_readable=False):
|
|||
|
||||
def backup_download(name):
|
||||
|
||||
if msettings.get("interface") != "api":
|
||||
if Moulinette.interface.type != "api":
|
||||
logger.error(
|
||||
"This option is only meant for the API/webadmin and doesn't make sense for the command line."
|
||||
)
|
||||
|
|
|
@ -28,7 +28,7 @@ import re
|
|||
import os
|
||||
import time
|
||||
|
||||
from moulinette import m18n, msettings
|
||||
from moulinette import m18n, Moulinette
|
||||
from moulinette.utils import log
|
||||
from moulinette.utils.filesystem import (
|
||||
read_json,
|
||||
|
@ -138,7 +138,7 @@ def diagnosis_show(
|
|||
url = yunopaste(content)
|
||||
|
||||
logger.info(m18n.n("log_available_on_yunopaste", url=url))
|
||||
if msettings.get("interface") == "api":
|
||||
if Moulinette.interface.type == "api":
|
||||
return {"url": url}
|
||||
else:
|
||||
return
|
||||
|
@ -219,7 +219,7 @@ def diagnosis_run(
|
|||
|
||||
if email:
|
||||
_email_diagnosis_issues()
|
||||
if issues and msettings.get("interface") == "cli":
|
||||
if issues and Moulinette.interface.type == "cli":
|
||||
logger.warning(m18n.n("diagnosis_display_tip"))
|
||||
|
||||
|
||||
|
@ -595,7 +595,7 @@ class Diagnoser:
|
|||
info[1].update(meta_data)
|
||||
s = m18n.n(info[0], **(info[1]))
|
||||
# In cli, we remove the html tags
|
||||
if msettings.get("interface") != "api" or force_remove_html_tags:
|
||||
if Moulinette.interface.type != "api" or force_remove_html_tags:
|
||||
s = s.replace("<cmd>", "'").replace("</cmd>", "'")
|
||||
s = html_tags.sub("", s.replace("<br>", "\n"))
|
||||
else:
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
import os
|
||||
import re
|
||||
|
||||
from moulinette import m18n, msettings, msignals
|
||||
from moulinette import m18n, Moulinette
|
||||
from moulinette.core import MoulinetteError
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
|
@ -166,7 +166,9 @@ def domain_add(operation_logger, domain, dyndns=False):
|
|||
# because it's one of the major service, but in the long term we
|
||||
# should identify the root of this bug...
|
||||
_force_clear_hashes(["/etc/nginx/conf.d/%s.conf" % domain])
|
||||
regen_conf(names=["nginx", "metronome", "dnsmasq", "postfix", "rspamd"])
|
||||
regen_conf(
|
||||
names=["nginx", "metronome", "dnsmasq", "postfix", "rspamd", "mdns"]
|
||||
)
|
||||
app_ssowatconf()
|
||||
|
||||
except Exception as e:
|
||||
|
@ -239,8 +241,8 @@ def domain_remove(operation_logger, domain, remove_apps=False, force=False):
|
|||
|
||||
if apps_on_that_domain:
|
||||
if remove_apps:
|
||||
if msettings.get("interface") == "cli" and not force:
|
||||
answer = msignals.prompt(
|
||||
if Moulinette.interface.type == "cli" and not force:
|
||||
answer = Moulinette.prompt(
|
||||
m18n.n(
|
||||
"domain_remove_confirm_apps_removal",
|
||||
apps="\n".join([x[1] for x in apps_on_that_domain]),
|
||||
|
@ -293,7 +295,7 @@ def domain_remove(operation_logger, domain, remove_apps=False, force=False):
|
|||
"/etc/nginx/conf.d/%s.conf" % domain, new_conf=None, save=True
|
||||
)
|
||||
|
||||
regen_conf(names=["nginx", "metronome", "dnsmasq", "postfix"])
|
||||
regen_conf(names=["nginx", "metronome", "dnsmasq", "postfix", "rspamd", "mdns"])
|
||||
app_ssowatconf()
|
||||
|
||||
hook_callback("post_domain_remove", args=[domain])
|
||||
|
@ -346,7 +348,7 @@ def domain_dns_conf(domain, ttl=None):
|
|||
for record in record_list:
|
||||
result += "\n{name} {ttl} IN {type} {value}".format(**record)
|
||||
|
||||
if msettings.get("interface") == "cli":
|
||||
if Moulinette.interface.type == "cli":
|
||||
logger.info(m18n.n("domain_dns_conf_is_just_a_recommendation"))
|
||||
|
||||
return result
|
||||
|
|
|
@ -31,7 +31,7 @@ import mimetypes
|
|||
from glob import iglob
|
||||
from importlib import import_module
|
||||
|
||||
from moulinette import m18n, msettings
|
||||
from moulinette import m18n, Moulinette
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from moulinette.utils import log
|
||||
from moulinette.utils.filesystem import read_json
|
||||
|
@ -416,7 +416,7 @@ def _hook_exec_bash(path, args, chdir, env, user, return_format, loggers):
|
|||
env = {}
|
||||
env["YNH_CWD"] = chdir
|
||||
|
||||
env["YNH_INTERFACE"] = msettings.get("interface")
|
||||
env["YNH_INTERFACE"] = Moulinette.interface.type
|
||||
|
||||
stdreturn = os.path.join(tempfile.mkdtemp(), "stdreturn")
|
||||
with open(stdreturn, "w") as f:
|
||||
|
|
|
@ -33,7 +33,7 @@ import psutil
|
|||
from datetime import datetime, timedelta
|
||||
from logging import FileHandler, getLogger, Formatter
|
||||
|
||||
from moulinette import m18n, msettings
|
||||
from moulinette import m18n, Moulinette
|
||||
from moulinette.core import MoulinetteError
|
||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from yunohost.utils.packages import get_ynh_package_version
|
||||
|
@ -44,7 +44,6 @@ CATEGORIES_PATH = "/var/log/yunohost/categories/"
|
|||
OPERATIONS_PATH = "/var/log/yunohost/categories/operation/"
|
||||
METADATA_FILE_EXT = ".yml"
|
||||
LOG_FILE_EXT = ".log"
|
||||
RELATED_CATEGORIES = ["app", "domain", "group", "service", "user"]
|
||||
|
||||
logger = getActionLogger("yunohost.log")
|
||||
|
||||
|
@ -125,7 +124,7 @@ def log_list(limit=None, with_details=False, with_suboperations=False):
|
|||
operations = list(reversed(sorted(operations, key=lambda o: o["name"])))
|
||||
# Reverse the order of log when in cli, more comfortable to read (avoid
|
||||
# unecessary scrolling)
|
||||
is_api = msettings.get("interface") == "api"
|
||||
is_api = Moulinette.interface.type == "api"
|
||||
if not is_api:
|
||||
operations = list(reversed(operations))
|
||||
|
||||
|
@ -214,7 +213,7 @@ def log_show(
|
|||
url = yunopaste(content)
|
||||
|
||||
logger.info(m18n.n("log_available_on_yunopaste", url=url))
|
||||
if msettings.get("interface") == "api":
|
||||
if Moulinette.interface.type == "api":
|
||||
return {"url": url}
|
||||
else:
|
||||
return
|
||||
|
@ -609,7 +608,7 @@ class OperationLogger(object):
|
|||
"operation": self.operation,
|
||||
"parent": self.parent,
|
||||
"yunohost_version": get_ynh_package_version("yunohost")["version"],
|
||||
"interface": msettings.get("interface"),
|
||||
"interface": Moulinette.interface.type,
|
||||
}
|
||||
if self.related_to is not None:
|
||||
data["related_to"] = self.related_to
|
||||
|
@ -663,7 +662,7 @@ class OperationLogger(object):
|
|||
self.logger.removeHandler(self.file_handler)
|
||||
self.file_handler.close()
|
||||
|
||||
is_api = msettings.get("interface") == "api"
|
||||
is_api = Moulinette.interface.type == "api"
|
||||
desc = _get_description_from_name(self.name)
|
||||
if error is None:
|
||||
if is_api:
|
||||
|
|
|
@ -37,10 +37,19 @@ from moulinette import m18n
|
|||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||
from moulinette.utils.process import check_output
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, append_to_file, write_to_file
|
||||
from moulinette.utils.filesystem import (
|
||||
read_file,
|
||||
append_to_file,
|
||||
write_to_file,
|
||||
read_yaml,
|
||||
write_to_yaml,
|
||||
)
|
||||
|
||||
MOULINETTE_LOCK = "/var/run/moulinette_yunohost.lock"
|
||||
|
||||
SERVICES_CONF = "/etc/yunohost/services.yml"
|
||||
SERVICES_CONF_BASE = "/usr/share/yunohost/templates/yunohost/services.yml"
|
||||
|
||||
logger = getActionLogger("yunohost.service")
|
||||
|
||||
|
||||
|
@ -114,7 +123,8 @@ def service_add(
|
|||
|
||||
try:
|
||||
_save_services(services)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.warning(e)
|
||||
# we'll get a logger.warning with more details in _save_services
|
||||
raise YunohostError("service_add_failed", service=name)
|
||||
|
||||
|
@ -633,17 +643,21 @@ def _get_services():
|
|||
|
||||
"""
|
||||
try:
|
||||
with open("/etc/yunohost/services.yml", "r") as f:
|
||||
services = yaml.safe_load(f) or {}
|
||||
services = read_yaml(SERVICES_CONF_BASE) or {}
|
||||
|
||||
# These are keys flagged 'null' in the base conf
|
||||
legacy_keys_to_delete = [k for k, v in services.items() if v is None]
|
||||
|
||||
services.update(read_yaml(SERVICES_CONF) or {})
|
||||
|
||||
services = {
|
||||
name: infos
|
||||
for name, infos in services.items()
|
||||
if name not in legacy_keys_to_delete
|
||||
}
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
# some services are marked as None to remove them from YunoHost
|
||||
# filter this
|
||||
for key, value in list(services.items()):
|
||||
if value is None:
|
||||
del services[key]
|
||||
|
||||
# Dirty hack to automatically find custom SSH port ...
|
||||
ssh_port_line = re.findall(
|
||||
r"\bPort *([0-9]{2,5})\b", read_file("/etc/ssh/sshd_config")
|
||||
|
@ -664,6 +678,13 @@ def _get_services():
|
|||
del services["postgresql"]["description"]
|
||||
services["postgresql"]["actual_systemd_service"] = "postgresql@13-main"
|
||||
|
||||
# Remove legacy /var/log/daemon.log and /var/log/syslog from log entries
|
||||
# because they are too general. Instead, now the journalctl log is
|
||||
# returned by default which is more relevant.
|
||||
for infos in services.values():
|
||||
if infos.get("log") in ["/var/log/syslog", "/var/log/daemon.log"]:
|
||||
del infos["log"]
|
||||
|
||||
return services
|
||||
|
||||
|
||||
|
@ -675,12 +696,26 @@ def _save_services(services):
|
|||
services -- A dict of managed services with their parameters
|
||||
|
||||
"""
|
||||
try:
|
||||
with open("/etc/yunohost/services.yml", "w") as f:
|
||||
yaml.safe_dump(services, f, default_flow_style=False)
|
||||
except Exception as e:
|
||||
logger.warning("Error while saving services, exception: %s", e, exc_info=1)
|
||||
raise
|
||||
|
||||
# Compute the diff with the base file
|
||||
# such that /etc/yunohost/services.yml contains the minimal
|
||||
# changes with respect to the base conf
|
||||
|
||||
conf_base = yaml.safe_load(open(SERVICES_CONF_BASE)) or {}
|
||||
|
||||
diff = {}
|
||||
|
||||
for service_name, service_infos in services.items():
|
||||
service_conf_base = conf_base.get(service_name, {})
|
||||
diff[service_name] = {}
|
||||
|
||||
for key, value in service_infos.items():
|
||||
if service_conf_base.get(key) != value:
|
||||
diff[service_name][key] = value
|
||||
|
||||
diff = {name: infos for name, infos in diff.items() if infos}
|
||||
|
||||
write_to_yaml(SERVICES_CONF, diff)
|
||||
|
||||
|
||||
def _tail(file, n):
|
||||
|
|
|
@ -102,6 +102,7 @@ DEFAULTS = OrderedDict(
|
|||
("ssowat.panel_overlay.enabled", {"type": "bool", "default": True}),
|
||||
("security.webadmin.allowlist.enabled", {"type": "bool", "default": False}),
|
||||
("security.webadmin.allowlist", {"type": "string", "default": ""}),
|
||||
("security.experimental.enabled", {"type": "bool", "default": False}),
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -399,6 +400,12 @@ def reconfigure_nginx(setting_name, old_value, new_value):
|
|||
regen_conf(names=["nginx"])
|
||||
|
||||
|
||||
@post_change_hook("security.experimental.enabled")
|
||||
def reconfigure_nginx_and_yunohost(setting_name, old_value, new_value):
|
||||
if old_value != new_value:
|
||||
regen_conf(names=["nginx", "yunohost"])
|
||||
|
||||
|
||||
@post_change_hook("security.ssh.compatibility")
|
||||
def reconfigure_ssh(setting_name, old_value, new_value):
|
||||
if old_value != new_value:
|
||||
|
|
|
@ -3,7 +3,7 @@ import pytest
|
|||
import sys
|
||||
|
||||
import moulinette
|
||||
from moulinette import m18n, msettings
|
||||
from moulinette import m18n, Moulinette
|
||||
from yunohost.utils.error import YunohostError
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
@ -81,4 +81,12 @@ def pytest_cmdline_main(config):
|
|||
import yunohost
|
||||
|
||||
yunohost.init(debug=config.option.yunodebug)
|
||||
msettings["interface"] = "test"
|
||||
|
||||
class DummyInterface:
|
||||
|
||||
type = "test"
|
||||
|
||||
def prompt(*args, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
Moulinette._interface = DummyInterface()
|
||||
|
|
|
@ -5,7 +5,7 @@ from mock import patch
|
|||
from io import StringIO
|
||||
from collections import OrderedDict
|
||||
|
||||
from moulinette import msignals
|
||||
from moulinette import Moulinette
|
||||
|
||||
from yunohost import domain, user
|
||||
from yunohost.app import _parse_args_in_yunohost_format, PasswordArgumentParser
|
||||
|
@ -84,7 +84,7 @@ def test_parse_args_in_yunohost_format_string_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_string": ("some_value", "string")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -97,7 +97,7 @@ def test_parse_args_in_yunohost_format_string_input_no_ask():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_string": ("some_value", "string")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -124,7 +124,7 @@ def test_parse_args_in_yunohost_format_string_optional_with_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_string": ("some_value", "string")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -139,7 +139,7 @@ def test_parse_args_in_yunohost_format_string_optional_with_empty_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_string": ("", "string")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value=""):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=""):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -153,7 +153,7 @@ def test_parse_args_in_yunohost_format_string_optional_with_input_without_ask():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_string": ("some_value", "string")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -180,7 +180,9 @@ def test_parse_args_in_yunohost_format_string_input_test_ask():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with(ask_text, False)
|
||||
|
||||
|
@ -197,7 +199,9 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_default():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with("%s (default: %s)" % (ask_text, default_text), False)
|
||||
|
||||
|
@ -215,7 +219,9 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_example():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
assert example_text in prompt.call_args[0][0]
|
||||
|
@ -234,7 +240,9 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_help():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
assert help_text in prompt.call_args[0][0]
|
||||
|
@ -251,7 +259,7 @@ def test_parse_args_in_yunohost_format_string_with_choice_prompt():
|
|||
questions = [{"name": "some_string", "type": "string", "choices": ["fr", "en"]}]
|
||||
answers = {"some_string": "fr"}
|
||||
expected_result = OrderedDict({"some_string": ("fr", "string")})
|
||||
with patch.object(msignals, "prompt", return_value="fr"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="fr"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -275,7 +283,7 @@ def test_parse_args_in_yunohost_format_string_with_choice_ask():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="ru") as prompt:
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="ru") as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
|
||||
|
@ -333,7 +341,7 @@ def test_parse_args_in_yunohost_format_password_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_password": ("some_value", "password")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -347,7 +355,7 @@ def test_parse_args_in_yunohost_format_password_input_no_ask():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_password": ("some_value", "password")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -383,7 +391,7 @@ def test_parse_args_in_yunohost_format_password_optional_with_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_password": ("some_value", "password")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -399,7 +407,7 @@ def test_parse_args_in_yunohost_format_password_optional_with_empty_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_password": ("", "password")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value=""):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=""):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -414,7 +422,7 @@ def test_parse_args_in_yunohost_format_password_optional_with_input_without_ask(
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_password": ("some_value", "password")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -462,7 +470,9 @@ def test_parse_args_in_yunohost_format_password_input_test_ask():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with(ask_text, True)
|
||||
|
||||
|
@ -481,7 +491,9 @@ def test_parse_args_in_yunohost_format_password_input_test_ask_with_example():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
assert example_text in prompt.call_args[0][0]
|
||||
|
@ -501,7 +513,9 @@ def test_parse_args_in_yunohost_format_password_input_test_ask_with_help():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
assert help_text in prompt.call_args[0][0]
|
||||
|
@ -594,7 +608,7 @@ def test_parse_args_in_yunohost_format_path_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_path": ("some_value", "path")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -608,7 +622,7 @@ def test_parse_args_in_yunohost_format_path_input_no_ask():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_path": ("some_value", "path")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -637,7 +651,7 @@ def test_parse_args_in_yunohost_format_path_optional_with_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_path": ("some_value", "path")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -653,7 +667,7 @@ def test_parse_args_in_yunohost_format_path_optional_with_empty_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_path": ("", "path")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value=""):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=""):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -668,7 +682,7 @@ def test_parse_args_in_yunohost_format_path_optional_with_input_without_ask():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_path": ("some_value", "path")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="some_value"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -697,7 +711,9 @@ def test_parse_args_in_yunohost_format_path_input_test_ask():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with(ask_text, False)
|
||||
|
||||
|
@ -715,7 +731,9 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_default():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with("%s (default: %s)" % (ask_text, default_text), False)
|
||||
|
||||
|
@ -734,7 +752,9 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_example():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
assert example_text in prompt.call_args[0][0]
|
||||
|
@ -754,7 +774,9 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_help():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="some_value") as prompt:
|
||||
with patch.object(
|
||||
Moulinette.interface, "prompt", return_value="some_value"
|
||||
) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
assert help_text in prompt.call_args[0][0]
|
||||
|
@ -918,11 +940,11 @@ def test_parse_args_in_yunohost_format_boolean_input():
|
|||
answers = {}
|
||||
|
||||
expected_result = OrderedDict({"some_boolean": (1, "boolean")})
|
||||
with patch.object(msignals, "prompt", return_value="y"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="y"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
expected_result = OrderedDict({"some_boolean": (0, "boolean")})
|
||||
with patch.object(msignals, "prompt", return_value="n"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="n"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -936,7 +958,7 @@ def test_parse_args_in_yunohost_format_boolean_input_no_ask():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_boolean": (1, "boolean")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="y"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="y"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -965,7 +987,7 @@ def test_parse_args_in_yunohost_format_boolean_optional_with_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_boolean": (1, "boolean")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="y"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="y"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -981,7 +1003,7 @@ def test_parse_args_in_yunohost_format_boolean_optional_with_empty_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_boolean": (0, "boolean")}) # default to false
|
||||
|
||||
with patch.object(msignals, "prompt", return_value=""):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=""):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -996,7 +1018,7 @@ def test_parse_args_in_yunohost_format_boolean_optional_with_input_without_ask()
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_boolean": (0, "boolean")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="n"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="n"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -1039,7 +1061,7 @@ def test_parse_args_in_yunohost_format_boolean_input_test_ask():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value=0) as prompt:
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=0) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with(ask_text + " [yes | no] (default: no)", False)
|
||||
|
||||
|
@ -1057,7 +1079,7 @@ def test_parse_args_in_yunohost_format_boolean_input_test_ask_with_default():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value=1) as prompt:
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=1) as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with("%s [yes | no] (default: yes)" % ask_text, False)
|
||||
|
||||
|
@ -1193,11 +1215,11 @@ def test_parse_args_in_yunohost_format_domain_two_domains_default_input():
|
|||
domain, "_get_maindomain", return_value=main_domain
|
||||
), patch.object(domain, "domain_list", return_value={"domains": domains}):
|
||||
expected_result = OrderedDict({"some_domain": (main_domain, "domain")})
|
||||
with patch.object(msignals, "prompt", return_value=main_domain):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=main_domain):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
expected_result = OrderedDict({"some_domain": (other_domain, "domain")})
|
||||
with patch.object(msignals, "prompt", return_value=other_domain):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=other_domain):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -1380,14 +1402,14 @@ def test_parse_args_in_yunohost_format_user_two_users_default_input():
|
|||
with patch.object(user, "user_list", return_value={"users": users}):
|
||||
with patch.object(user, "user_info", return_value={}):
|
||||
expected_result = OrderedDict({"some_user": (username, "user")})
|
||||
with patch.object(msignals, "prompt", return_value=username):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=username):
|
||||
assert (
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
== expected_result
|
||||
)
|
||||
|
||||
expected_result = OrderedDict({"some_user": (other_user, "user")})
|
||||
with patch.object(msignals, "prompt", return_value=other_user):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=other_user):
|
||||
assert (
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
== expected_result
|
||||
|
@ -1447,14 +1469,14 @@ def test_parse_args_in_yunohost_format_number_input():
|
|||
answers = {}
|
||||
|
||||
expected_result = OrderedDict({"some_number": (1337, "number")})
|
||||
with patch.object(msignals, "prompt", return_value="1337"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="1337"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
with patch.object(msignals, "prompt", return_value=1337):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=1337):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
expected_result = OrderedDict({"some_number": (0, "number")})
|
||||
with patch.object(msignals, "prompt", return_value=""):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value=""):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -1468,7 +1490,7 @@ def test_parse_args_in_yunohost_format_number_input_no_ask():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_number": (1337, "number")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="1337"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="1337"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -1497,7 +1519,7 @@ def test_parse_args_in_yunohost_format_number_optional_with_input():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_number": (1337, "number")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="1337"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="1337"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -1512,7 +1534,7 @@ def test_parse_args_in_yunohost_format_number_optional_with_input_without_ask():
|
|||
answers = {}
|
||||
expected_result = OrderedDict({"some_number": (0, "number")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="0"):
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="0"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
|
@ -1555,7 +1577,7 @@ def test_parse_args_in_yunohost_format_number_input_test_ask():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="1111") as prompt:
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="1111") as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with("%s (default: 0)" % (ask_text), False)
|
||||
|
||||
|
@ -1573,7 +1595,7 @@ def test_parse_args_in_yunohost_format_number_input_test_ask_with_default():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="1111") as prompt:
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="1111") as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
prompt.assert_called_with("%s (default: %s)" % (ask_text, default_value), False)
|
||||
|
||||
|
@ -1592,7 +1614,7 @@ def test_parse_args_in_yunohost_format_number_input_test_ask_with_example():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="1111") as prompt:
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="1111") as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
assert example_value in prompt.call_args[0][0]
|
||||
|
@ -1612,7 +1634,7 @@ def test_parse_args_in_yunohost_format_number_input_test_ask_with_help():
|
|||
]
|
||||
answers = {}
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="1111") as prompt:
|
||||
with patch.object(Moulinette.interface, "prompt", return_value="1111") as prompt:
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert ask_text in prompt.call_args[0][0]
|
||||
assert help_value in prompt.call_args[0][0]
|
||||
|
|
59
src/yunohost/tests/test_ldapauth.py
Normal file
59
src/yunohost/tests/test_ldapauth.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
import pytest
|
||||
import os
|
||||
|
||||
from yunohost.authenticators.ldap_admin import Authenticator as LDAPAuth
|
||||
from yunohost.tools import tools_adminpw
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.core import MoulinetteError
|
||||
|
||||
|
||||
def setup_function(function):
|
||||
|
||||
if os.system("systemctl is-active slapd") != 0:
|
||||
os.system("systemctl start slapd && sleep 3")
|
||||
|
||||
tools_adminpw("yunohost", check_strength=False)
|
||||
|
||||
|
||||
def test_authenticate():
|
||||
LDAPAuth().authenticate_credentials(credentials="yunohost")
|
||||
|
||||
|
||||
def test_authenticate_with_wrong_password():
|
||||
with pytest.raises(MoulinetteError) as exception:
|
||||
LDAPAuth().authenticate_credentials(credentials="bad_password_lul")
|
||||
|
||||
translation = m18n.n("invalid_password")
|
||||
expected_msg = translation.format()
|
||||
assert expected_msg in str(exception)
|
||||
|
||||
|
||||
def test_authenticate_server_down(mocker):
|
||||
os.system("systemctl stop slapd && sleep 3")
|
||||
|
||||
# Now if slapd is down, moulinette tries to restart it
|
||||
mocker.patch("os.system")
|
||||
mocker.patch("time.sleep")
|
||||
with pytest.raises(MoulinetteError) as exception:
|
||||
LDAPAuth().authenticate_credentials(credentials="yunohost")
|
||||
|
||||
translation = m18n.n("ldap_server_down")
|
||||
expected_msg = translation.format()
|
||||
assert expected_msg in str(exception)
|
||||
|
||||
|
||||
def test_authenticate_change_password():
|
||||
|
||||
LDAPAuth().authenticate_credentials(credentials="yunohost")
|
||||
|
||||
tools_adminpw("plopette", check_strength=False)
|
||||
|
||||
with pytest.raises(MoulinetteError) as exception:
|
||||
LDAPAuth().authenticate_credentials(credentials="yunohost")
|
||||
|
||||
translation = m18n.n("invalid_password")
|
||||
expected_msg = translation.format()
|
||||
assert expected_msg in str(exception)
|
||||
|
||||
LDAPAuth().authenticate_credentials(credentials="plopette")
|
|
@ -30,7 +30,7 @@ import time
|
|||
from importlib import import_module
|
||||
from packaging import version
|
||||
|
||||
from moulinette import msignals, m18n
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.process import check_output, call_async_output
|
||||
from moulinette.utils.filesystem import read_yaml, write_to_yaml
|
||||
|
@ -665,7 +665,7 @@ def tools_shutdown(operation_logger, force=False):
|
|||
if not shutdown:
|
||||
try:
|
||||
# Ask confirmation for server shutdown
|
||||
i = msignals.prompt(m18n.n("server_shutdown_confirm", answers="y/N"))
|
||||
i = Moulinette.prompt(m18n.n("server_shutdown_confirm", answers="y/N"))
|
||||
except NotImplemented:
|
||||
pass
|
||||
else:
|
||||
|
@ -684,7 +684,7 @@ def tools_reboot(operation_logger, force=False):
|
|||
if not reboot:
|
||||
try:
|
||||
# Ask confirmation for restoring
|
||||
i = msignals.prompt(m18n.n("server_reboot_confirm", answers="y/N"))
|
||||
i = Moulinette.prompt(m18n.n("server_reboot_confirm", answers="y/N"))
|
||||
except NotImplemented:
|
||||
pass
|
||||
else:
|
||||
|
|
|
@ -33,7 +33,7 @@ import string
|
|||
import subprocess
|
||||
import copy
|
||||
|
||||
from moulinette import msignals, msettings, m18n
|
||||
from moulinette import Moulinette, m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.process import check_output
|
||||
|
||||
|
@ -110,18 +110,18 @@ def user_create(
|
|||
|
||||
# Validate domain used for email address/xmpp account
|
||||
if domain is None:
|
||||
if msettings.get("interface") == "api":
|
||||
if Moulinette.interface.type == "api":
|
||||
raise YunohostValidationError(
|
||||
"Invalid usage, you should specify a domain argument"
|
||||
)
|
||||
else:
|
||||
# On affiche les differents domaines possibles
|
||||
msignals.display(m18n.n("domains_available"))
|
||||
Moulinette.display(m18n.n("domains_available"))
|
||||
for domain in domain_list()["domains"]:
|
||||
msignals.display("- {}".format(domain))
|
||||
Moulinette.display("- {}".format(domain))
|
||||
|
||||
maindomain = _get_maindomain()
|
||||
domain = msignals.prompt(
|
||||
domain = Moulinette.prompt(
|
||||
m18n.n("ask_user_domain") + " (default: %s)" % maindomain
|
||||
)
|
||||
if not domain:
|
||||
|
@ -372,8 +372,8 @@ def user_update(
|
|||
# when in the cli interface if the option to change the password is called
|
||||
# without a specified value, change_password will be set to the const 0.
|
||||
# In this case we prompt for the new password.
|
||||
if msettings.get("interface") == "cli" and not change_password:
|
||||
change_password = msignals.prompt(m18n.n("ask_password"), True, True)
|
||||
if Moulinette.interface.type == "cli" and not change_password:
|
||||
change_password = Moulinette.prompt(m18n.n("ask_password"), True, True)
|
||||
# Ensure sufficiently complex password
|
||||
assert_password_is_strong_enough("user", change_password)
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" License
|
||||
|
||||
Copyright (C) 2019 YunoHost
|
||||
|
@ -21,10 +20,18 @@
|
|||
|
||||
import os
|
||||
import atexit
|
||||
from moulinette.core import MoulinetteLdapIsDownError
|
||||
from moulinette.authenticators import ldap
|
||||
import logging
|
||||
import ldap
|
||||
import ldap.sasl
|
||||
import time
|
||||
import ldap.modlist as modlist
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.core import MoulinetteError
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
||||
logger = logging.getLogger("yunohost.utils.ldap")
|
||||
|
||||
# We use a global variable to do some caching
|
||||
# to avoid re-authenticating in case we call _get_ldap_authenticator multiple times
|
||||
_ldap_interface = None
|
||||
|
@ -35,47 +42,17 @@ def _get_ldap_interface():
|
|||
global _ldap_interface
|
||||
|
||||
if _ldap_interface is None:
|
||||
|
||||
conf = {
|
||||
"vendor": "ldap",
|
||||
"name": "as-root",
|
||||
"parameters": {
|
||||
"uri": "ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi",
|
||||
"base_dn": "dc=yunohost,dc=org",
|
||||
"user_rdn": "gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth",
|
||||
},
|
||||
"extra": {},
|
||||
}
|
||||
|
||||
try:
|
||||
_ldap_interface = ldap.Authenticator(**conf)
|
||||
except MoulinetteLdapIsDownError:
|
||||
raise YunohostError(
|
||||
"Service slapd is not running but is required to perform this action ... You can try to investigate what's happening with 'systemctl status slapd'"
|
||||
)
|
||||
|
||||
assert_slapd_is_running()
|
||||
_ldap_interface = LDAPInterface()
|
||||
|
||||
return _ldap_interface
|
||||
|
||||
|
||||
def assert_slapd_is_running():
|
||||
|
||||
# Assert slapd is running...
|
||||
if not os.system("pgrep slapd >/dev/null") == 0:
|
||||
raise YunohostError(
|
||||
"Service slapd is not running but is required to perform this action ... You can try to investigate what's happening with 'systemctl status slapd'"
|
||||
)
|
||||
|
||||
|
||||
# We regularly want to extract stuff like 'bar' in ldap path like
|
||||
# foo=bar,dn=users.example.org,ou=example.org,dc=org so this small helper allow
|
||||
# to do this without relying of dozens of mysterious string.split()[0]
|
||||
#
|
||||
# e.g. using _ldap_path_extract(path, "foo") on the previous example will
|
||||
# return bar
|
||||
|
||||
|
||||
def _ldap_path_extract(path, info):
|
||||
for element in path.split(","):
|
||||
if element.startswith(info + "="):
|
||||
|
@ -93,3 +70,246 @@ def _destroy_ldap_interface():
|
|||
|
||||
|
||||
atexit.register(_destroy_ldap_interface)
|
||||
|
||||
|
||||
class LDAPInterface:
|
||||
def __init__(self):
|
||||
logger.debug("initializing ldap interface")
|
||||
|
||||
self.uri = "ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi"
|
||||
self.basedn = "dc=yunohost,dc=org"
|
||||
self.rootdn = "gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth"
|
||||
self.connect()
|
||||
|
||||
def connect(self):
|
||||
def _reconnect():
|
||||
con = ldap.ldapobject.ReconnectLDAPObject(
|
||||
self.uri, retry_max=10, retry_delay=0.5
|
||||
)
|
||||
con.sasl_non_interactive_bind_s("EXTERNAL")
|
||||
return con
|
||||
|
||||
try:
|
||||
con = _reconnect()
|
||||
except ldap.SERVER_DOWN:
|
||||
# ldap is down, attempt to restart it before really failing
|
||||
logger.warning(m18n.n("ldap_server_is_down_restart_it"))
|
||||
os.system("systemctl restart slapd")
|
||||
time.sleep(10) # waits 10 secondes so we are sure that slapd has restarted
|
||||
try:
|
||||
con = _reconnect()
|
||||
except ldap.SERVER_DOWN:
|
||||
raise YunohostError(
|
||||
"Service slapd is not running but is required to perform this action ... "
|
||||
"You can try to investigate what's happening with 'systemctl status slapd'"
|
||||
)
|
||||
|
||||
# Check that we are indeed logged in with the right identity
|
||||
try:
|
||||
# whoami_s return dn:..., then delete these 3 characters
|
||||
who = con.whoami_s()[3:]
|
||||
except Exception as e:
|
||||
logger.warning("Error during ldap authentication process: %s", e)
|
||||
raise
|
||||
else:
|
||||
if who != self.rootdn:
|
||||
raise MoulinetteError("Not logged in with the expected userdn ?!")
|
||||
else:
|
||||
self.con = con
|
||||
|
||||
def __del__(self):
|
||||
"""Disconnect and free ressources"""
|
||||
if hasattr(self, "con") and self.con:
|
||||
self.con.unbind_s()
|
||||
|
||||
def search(self, base=None, filter="(objectClass=*)", attrs=["dn"]):
|
||||
"""Search in LDAP base
|
||||
|
||||
Perform an LDAP search operation with given arguments and return
|
||||
results as a list.
|
||||
|
||||
Keyword arguments:
|
||||
- base -- The dn to search into
|
||||
- filter -- A string representation of the filter to apply
|
||||
- attrs -- A list of attributes to fetch
|
||||
|
||||
Returns:
|
||||
A list of all results
|
||||
|
||||
"""
|
||||
if not base:
|
||||
base = self.basedn
|
||||
|
||||
try:
|
||||
result = self.con.search_s(base, ldap.SCOPE_SUBTREE, filter, attrs)
|
||||
except Exception as e:
|
||||
raise MoulinetteError(
|
||||
"error during LDAP search operation with: base='%s', "
|
||||
"filter='%s', attrs=%s and exception %s" % (base, filter, attrs, e),
|
||||
raw_msg=True,
|
||||
)
|
||||
|
||||
result_list = []
|
||||
if not attrs or "dn" not in attrs:
|
||||
result_list = [entry for dn, entry in result]
|
||||
else:
|
||||
for dn, entry in result:
|
||||
entry["dn"] = [dn]
|
||||
result_list.append(entry)
|
||||
|
||||
def decode(value):
|
||||
if isinstance(value, bytes):
|
||||
value = value.decode("utf-8")
|
||||
return value
|
||||
|
||||
# result_list is for example :
|
||||
# [{'virtualdomain': [b'test.com']}, {'virtualdomain': [b'yolo.test']},
|
||||
for stuff in result_list:
|
||||
if isinstance(stuff, dict):
|
||||
for key, values in stuff.items():
|
||||
stuff[key] = [decode(v) for v in values]
|
||||
|
||||
return result_list
|
||||
|
||||
def add(self, rdn, attr_dict):
|
||||
"""
|
||||
Add LDAP entry
|
||||
|
||||
Keyword arguments:
|
||||
rdn -- DN without domain
|
||||
attr_dict -- Dictionnary of attributes/values to add
|
||||
|
||||
Returns:
|
||||
Boolean | MoulinetteError
|
||||
|
||||
"""
|
||||
dn = rdn + "," + self.basedn
|
||||
ldif = modlist.addModlist(attr_dict)
|
||||
for i, (k, v) in enumerate(ldif):
|
||||
if isinstance(v, list):
|
||||
v = [a.encode("utf-8") for a in v]
|
||||
elif isinstance(v, str):
|
||||
v = [v.encode("utf-8")]
|
||||
ldif[i] = (k, v)
|
||||
|
||||
try:
|
||||
self.con.add_s(dn, ldif)
|
||||
except Exception as e:
|
||||
raise MoulinetteError(
|
||||
"error during LDAP add operation with: rdn='%s', "
|
||||
"attr_dict=%s and exception %s" % (rdn, attr_dict, e),
|
||||
raw_msg=True,
|
||||
)
|
||||
else:
|
||||
return True
|
||||
|
||||
def remove(self, rdn):
|
||||
"""
|
||||
Remove LDAP entry
|
||||
|
||||
Keyword arguments:
|
||||
rdn -- DN without domain
|
||||
|
||||
Returns:
|
||||
Boolean | MoulinetteError
|
||||
|
||||
"""
|
||||
dn = rdn + "," + self.basedn
|
||||
try:
|
||||
self.con.delete_s(dn)
|
||||
except Exception as e:
|
||||
raise MoulinetteError(
|
||||
"error during LDAP delete operation with: rdn='%s' and exception %s"
|
||||
% (rdn, e),
|
||||
raw_msg=True,
|
||||
)
|
||||
else:
|
||||
return True
|
||||
|
||||
def update(self, rdn, attr_dict, new_rdn=False):
|
||||
"""
|
||||
Modify LDAP entry
|
||||
|
||||
Keyword arguments:
|
||||
rdn -- DN without domain
|
||||
attr_dict -- Dictionnary of attributes/values to add
|
||||
new_rdn -- New RDN for modification
|
||||
|
||||
Returns:
|
||||
Boolean | MoulinetteError
|
||||
|
||||
"""
|
||||
dn = rdn + "," + self.basedn
|
||||
actual_entry = self.search(base=dn, attrs=None)
|
||||
ldif = modlist.modifyModlist(actual_entry[0], attr_dict, ignore_oldexistent=1)
|
||||
|
||||
if ldif == []:
|
||||
logger.debug("Nothing to update in LDAP")
|
||||
return True
|
||||
|
||||
try:
|
||||
if new_rdn:
|
||||
self.con.rename_s(dn, new_rdn)
|
||||
new_base = dn.split(",", 1)[1]
|
||||
dn = new_rdn + "," + new_base
|
||||
|
||||
for i, (a, k, vs) in enumerate(ldif):
|
||||
if isinstance(vs, list):
|
||||
vs = [v.encode("utf-8") for v in vs]
|
||||
elif isinstance(vs, str):
|
||||
vs = [vs.encode("utf-8")]
|
||||
ldif[i] = (a, k, vs)
|
||||
|
||||
self.con.modify_ext_s(dn, ldif)
|
||||
except Exception as e:
|
||||
raise MoulinetteError(
|
||||
"error during LDAP update operation with: rdn='%s', "
|
||||
"attr_dict=%s, new_rdn=%s and exception: %s"
|
||||
% (rdn, attr_dict, new_rdn, e),
|
||||
raw_msg=True,
|
||||
)
|
||||
else:
|
||||
return True
|
||||
|
||||
def validate_uniqueness(self, value_dict):
|
||||
"""
|
||||
Check uniqueness of values
|
||||
|
||||
Keyword arguments:
|
||||
value_dict -- Dictionnary of attributes/values to check
|
||||
|
||||
Returns:
|
||||
Boolean | MoulinetteError
|
||||
|
||||
"""
|
||||
attr_found = self.get_conflict(value_dict)
|
||||
if attr_found:
|
||||
logger.info(
|
||||
"attribute '%s' with value '%s' is not unique",
|
||||
attr_found[0],
|
||||
attr_found[1],
|
||||
)
|
||||
raise MoulinetteError(
|
||||
"ldap_attribute_already_exists",
|
||||
attribute=attr_found[0],
|
||||
value=attr_found[1],
|
||||
)
|
||||
return True
|
||||
|
||||
def get_conflict(self, value_dict, base_dn=None):
|
||||
"""
|
||||
Check uniqueness of values
|
||||
|
||||
Keyword arguments:
|
||||
value_dict -- Dictionnary of attributes/values to check
|
||||
|
||||
Returns:
|
||||
None | tuple with Fist conflict attribute name and value
|
||||
|
||||
"""
|
||||
for attr, value in value_dict.items():
|
||||
if not self.search(base=base_dn, filter=attr + "=" + value):
|
||||
continue
|
||||
else:
|
||||
return (attr, value)
|
||||
return None
|
||||
|
|
|
@ -35,6 +35,7 @@ def find_expected_string_keys():
|
|||
python_files = glob.glob("src/yunohost/*.py")
|
||||
python_files.extend(glob.glob("src/yunohost/utils/*.py"))
|
||||
python_files.extend(glob.glob("src/yunohost/data_migrations/*.py"))
|
||||
python_files.extend(glob.glob("src/yunohost/authenticators/*.py"))
|
||||
python_files.extend(glob.glob("data/hooks/diagnosis/*.py"))
|
||||
python_files.append("bin/yunohost")
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue