Merge branch 'stretch-unstable' into maindomain_ux_feedback

This commit is contained in:
Alexandre Aubin 2019-11-04 22:13:20 +01:00 committed by GitHub
commit bc965dc9f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 2115 additions and 1080 deletions

4
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,4 @@
# These are supported funding model platforms
custom: https://donate.yunohost.org
liberapay: YunoHost

View file

@ -1,48 +1,43 @@
<p align="center">
<img alt="YunoHost" src="https://raw.githubusercontent.com/YunoHost/doc/master/images/logo_roundcorner.png" width="100px" />
</p>
<h1 align="center">YunoHost</h1>
<div align="center">
[![Build status](https://travis-ci.org/YunoHost/yunohost.svg?branch=stretch-unstable)](https://travis-ci.org/YunoHost/yunohost) [![Build status](https://travis-ci.org/YunoHost/yunohost.svg?branch=stretch-unstable)](https://travis-ci.org/YunoHost/yunohost)
[![GitHub license](https://img.shields.io/github/license/YunoHost/yunohost)](https://github.com/YunoHost/yunohost/blob/stretch-unstable/LICENSE) [![GitHub license](https://img.shields.io/github/license/YunoHost/yunohost)](https://github.com/YunoHost/yunohost/blob/stretch-unstable/LICENSE)
[![Mastodon Follow](https://img.shields.io/mastodon/follow/28084)](https://mastodon.social/@yunohost)
# YunoHost core </div>
This repository is the core of YunoHost code. YunoHost is an operating system aiming to simplify as much as possible the administration of a server.
This repository corresponds to the core code of YunoHost, mainly written in Python and Bash.
- [Project features](https://yunohost.org/#/whatsyunohost)
- [Project website](https://yunohost.org) - [Project website](https://yunohost.org)
- [Bugtracker](https://github.com/YunoHost/issues). - [Install documentation](https://yunohost.org/install)
- [Issue tracker](https://github.com/YunoHost/issues)
# Screenshots
Webadmin ([Yunohost-Admin](https://github.com/YunoHost/yunohost-admin)) | Single sign-on user portal ([SSOwat](https://github.com/YunoHost/ssowat))
--- | ---
![](https://raw.githubusercontent.com/YunoHost/doc/master/images/webadmin.png) | ![](https://raw.githubusercontent.com/YunoHost/doc/master/images/user_panel.png)
## Contributing ## Contributing
- You can develop on this repository using [ynh-dev](https://github.com/YunoHost/ynh-dev) with `use-git` sub-command. - You can learn how to get started with developing on YunoHost by reading [this piece of documentation](https://yunohost.org/dev).
- On this repository we are [following this workflow](https://yunohost.org/#/build_system_en): `stable ← testing ← unstable ← your_branch`. - Come chat with us on the [dev chatroom](https://yunohost.org/#/chat_rooms) !
- Note: If you modify Python scripts, you will have to modifiy the actions map.
- You can help translate YunoHost on our [translation platform](https://translate.yunohost.org/engage/yunohost/?utm_source=widget) - 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/-/multi-auto.svg" alt="Translation status" />
</p>
## Repository content
- [YunoHost core Python 2.7 scripts](./src/yunohost).
- [An actionsmap](./data/actionsmap/yunohost.yml) used by moulinette.
- [Services configuration templates](./data/templates).
- [Hooks](./data/hooks).
- [Locales](./locales) for translations of `yunohost` command.
- [Shell helpers](./helpers.d) for [application packaging](https://yunohost.org/#/packaging_apps_helpers_en).
- [Modules for the XMPP server Metronome](./lib/metronome/modules).
- [Debian files](./debian) for package creation.
## How does it work?
- Python core scripts are accessible through two interfaces thanks to the [moulinette framework](https://github.com/YunoHost/moulinette):
- [CLI](https://en.wikipedia.org/wiki/Command-line_interface) for `yunohost` command.
- [API](https://en.wikipedia.org/wiki/Application_programming_interface) for [web administration module](https://github.com/YunoHost/yunohost-admin) (other modules could be implemented).
- You can find more details about how YunoHost works on this [documentation (in French)](https://yunohost.org/#/package_list_fr).
## Dependencies
- [Python 2.7](https://www.python.org/download/releases/2.7)
- [Moulinette](https://github.com/YunoHost/moulinette)
- [Bash](https://www.gnu.org/software/bash/bash.html)
- [Debian Stretch](https://www.debian.org/releases/stretch)
## License ## License
As [other components of YunoHost core code](https://yunohost.org/#/faq_en), this repository is licensed GNU AGPL v3. As [other components of YunoHost](https://yunohost.org/#/faq_en), this repository is licensed under GNU AGPL v3.

View file

@ -145,7 +145,7 @@ def _init_moulinette(debug=False, quiet=False):
}, },
'moulinette': { 'moulinette': {
'level': level, 'level': level,
'handlers': [], 'handlers': handlers,
'propagate': True, 'propagate': True,
}, },
'moulinette.interface': { 'moulinette.interface': {

View file

@ -285,7 +285,7 @@ user:
### user_permission_list() ### user_permission_list()
list: list:
action_help: List permissions and corresponding accesses action_help: List permissions and corresponding accesses
api: GET /users/permissions/<permission> api: GET /users/permissions
arguments: arguments:
-s: -s:
full: --short full: --short
@ -300,7 +300,7 @@ user:
### user_permission_update() ### user_permission_update()
update: update:
action_help: Manage group or user permissions action_help: Manage group or user permissions
api: POST /users/permissions/<permission> api: PUT /users/permissions/<permission>
arguments: arguments:
permission: permission:
help: Permission to manage (e.g. mail or nextcloud or wordpress.editors) help: Permission to manage (e.g. mail or nextcloud or wordpress.editors)
@ -769,14 +769,6 @@ app:
full: --sql full: --sql
help: Initial SQL file help: Initial SQL file
### app_debug()
debug:
action_help: Display all debug informations for an application
api: GET /apps/<app>/debug
arguments:
app:
help: App name
### app_makedefault() ### app_makedefault()
makedefault: makedefault:
action_help: Redirect domain root to an app action_help: Redirect domain root to an app

View file

@ -218,6 +218,27 @@ ynh_install_app_dependencies () {
fi fi
local dep_app=${app//_/-} # Replace all '_' by '-' local dep_app=${app//_/-} # Replace all '_' by '-'
#
# Epic ugly hack to fix the goddamn dependency nightmare of sury
# Sponsored by the "Djeezusse Fokin Kraiste Why Do Adminsys Has To Be So Fucking Complicated I Should Go Grow Potatoes Instead Of This Shit" collective
# https://github.com/YunoHost/issues/issues/1407
#
# If we require to install php dependency
if echo $dependencies | grep -q 'php';
then
# And we have packages from sury installed (7.0.33-10+weirdshiftafter instead of 7.0.33-0 on debian)
if dpkg --list | grep "php7.0" | grep -q -v "7.0.33-0+deb9"
then
# And sury ain't already installed
if ! grep -nrq "sury" /etc/apt/sources.list*
then
# Re-add sury
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/sury.list
wget -O /etc/apt/trusted.gpg.d/sury.gpg https://packages.sury.org/php/apt.gpg
fi
fi
fi
cat > /tmp/${dep_app}-ynh-deps.control << EOF # Make a control file for equivs-build cat > /tmp/${dep_app}-ynh-deps.control << EOF # Make a control file for equivs-build
Section: misc Section: misc
Priority: optional Priority: optional

View file

@ -40,10 +40,13 @@ ynh_use_logrotate () {
fi fi
if [ $# -gt 0 ] && [ "$(echo ${1:0:1})" != "-" ]; then if [ $# -gt 0 ] && [ "$(echo ${1:0:1})" != "-" ]; then
if [ "$(echo ${1##*.})" == "log" ]; then # Keep only the extension to check if it's a logfile # If the given logfile parameter already exists as a file, or if it ends up with ".log",
local logfile=$1 # In this case, focus logrotate on the logfile # we just want to manage a single file
if [ -f "$1" ] || [ "$(echo ${1##*.})" == "log" ]; then
local logfile=$1
# Otherwise we assume we want to manage a directory and all its .log file inside
else else
local logfile=$1/*.log # Else, uses the directory and all logfile into it. local logfile=$1/*.log
fi fi
fi fi
# LEGACY CODE # LEGACY CODE
@ -54,7 +57,7 @@ ynh_use_logrotate () {
fi fi
if [ -n "$logfile" ] if [ -n "$logfile" ]
then then
if [ "$(echo ${logfile##*.})" != "log" ]; then # Keep only the extension to check if it's a logfile if [ ! -f "$1" ] && [ "$(echo ${logfile##*.})" != "log" ]; then # Keep only the extension to check if it's a logfile
local logfile="$logfile/*.log" # Else, uses the directory and all logfile into it. local logfile="$logfile/*.log" # Else, uses the directory and all logfile into it.
fi fi
else else

View file

@ -159,7 +159,7 @@ ynh_add_protected_uris() {
ynh_app_setting() ynh_app_setting()
{ {
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python - <<EOF ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python - <<EOF
import os, yaml import os, yaml, sys
app, action = os.environ['APP'], os.environ['ACTION'].lower() app, action = os.environ['APP'], os.environ['ACTION'].lower()
key, value = os.environ['KEY'], os.environ.get('VALUE', None) key, value = os.environ['KEY'], os.environ.get('VALUE', None)
setting_file = "/etc/yunohost/apps/%s/settings.yml" % app setting_file = "/etc/yunohost/apps/%s/settings.yml" % app
@ -176,12 +176,21 @@ else:
elif action == "set": elif action == "set":
if key in ['redirected_urls', 'redirected_regex']: if key in ['redirected_urls', 'redirected_regex']:
value = yaml.load(value) value = yaml.load(value)
if any(key.startswith(word+"_") for word in ["unprotected", "protected", "skipped"]):
sys.stderr.write("/!\\ Packagers! This app is still using the skipped/protected/unprotected_uris/regex settings which are now obsolete and deprecated... Instead, you should use the new helpers 'ynh_permission_{create,urls,update,delete}' and the 'visitors' group to initialize the public/private access. Check out the documentation at the bottom of yunohost.org/groups_and_permissions to learn how to use the new permission mechanism.\n")
settings[key] = value settings[key] = value
else: else:
raise ValueError("action should either be get, set or delete") raise ValueError("action should either be get, set or delete")
with open(setting_file, "w") as f: with open(setting_file, "w") as f:
yaml.safe_dump(settings, f, default_flow_style=False) yaml.safe_dump(settings, f, default_flow_style=False)
EOF EOF
# Fucking legacy permission management.
# We need this because app temporarily set the app as unprotected to configure it with curl...
if [[ "$3" =~ ^(unprotected|skipped)_ ]] && [[ "${4:-}" == "/" ]]
then
ynh_permission_update --permission "main" --remove "all_users" --add "visitors"
fi
} }
# Check availability of a web path # Check availability of a web path
@ -230,29 +239,51 @@ ynh_webpath_register () {
# Create a new permission for the app # Create a new permission for the app
# #
# usage: ynh_permission_create --permission "permission" [--urls "url" ["url" ...]] # example: ynh_permission_create --permission admin --url /admin --allowed alice bob
# | arg: permission - the name for the permission (by default a permission named "main" already exist) #
# | arg: urls - (optional) a list of FULL urls for the permission (e.g. domain.tld/apps/admin) # usage: ynh_permission_create --permission "permission" [--url "url"] [--allowed group1 group2]
# | arg: permission - the name for the permission (by default a permission named "main" already exist)
# | arg: url - (optional) URL for which access will be allowed/forbidden
# | arg: allowed - (optional) A list of group/user to allow for the permission
#
# If provided, 'url' is assumed to be relative to the app domain/path if they
# start with '/'. For example:
# / -> domain.tld/app
# /admin -> domain.tld/app/admin
# domain.tld/app/api -> domain.tld/app/api
#
# 'url' can be later treated as a regex if it starts with "re:".
# For example:
# re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
# re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
# #
# example: ynh_permission_create --permission admin --urls domain.tld/blog/admin
ynh_permission_create() { ynh_permission_create() {
declare -Ar args_array=( [p]=permission= [u]=urls= ) declare -Ar args_array=( [p]=permission= [u]=url= [a]=allowed= )
local permission local permission
local urls local url
local allowed
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
if [[ -n ${urls:-} ]]; then if [[ -n ${url:-} ]]; then
urls=",urls=['${urls//';'/"','"}']" url="'$url'"
else
url="None"
fi fi
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission' ${urls:-}, sync_perm=False)"
if [[ -n ${allowed:-} ]]; then
allowed=",allowed=['${allowed//';'/"','"}']"
fi
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission', url=$url ${allowed:-} , sync_perm=False)"
} }
# Remove a permission for the app (note that when the app is removed all permission is automatically removed) # Remove a permission for the app (note that when the app is removed all permission is automatically removed)
# #
# usage: ynh_permission_remove --permission "permission" # example: ynh_permission_delete --permission editors
#
# usage: ynh_permission_delete --permission "permission"
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed) # | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# #
# example: ynh_permission_delete --permission editors
ynh_permission_delete() { ynh_permission_delete() {
declare -Ar args_array=( [p]=permission= ) declare -Ar args_array=( [p]=permission= )
local permission local permission
@ -261,30 +292,28 @@ ynh_permission_delete() {
yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app.$permission', sync_perm=False)" yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app.$permission', sync_perm=False)"
} }
# Manage urls related to a permission # Redefine the url associated to a permission
# #
# usage: ynh_permission_urls --permission "permission" --add "url" ["url" ...] --remove "url" ["url" ...] # usage: ynh_permission_url --permission "permission" --url "url"
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed) # | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# | arg: add - (optional) a list of FULL urls to add to the permission (e.g. domain.tld/apps/admin) # | arg: url - (optional) URL for which access will be allowed/forbidden
# | arg: remove - (optional) a list of FULL urls to remove from the permission (e.g. other.tld/apps/admin)
# #
ynh_permission_urls() { ynh_permission_url() {
declare -Ar args_array=([p]=permission= [a]=add= [r]=remove=) declare -Ar args_array=([p]=permission= [u]=url=)
local permission local permission
local add local url
local remove
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
if [[ -n ${add:-} ]]; then if [[ -n ${url:-} ]]; then
add=",add=['${add//';'/"','"}']" url="'$url'"
fi else
if [[ -n ${remove:-} ]]; then url="None"
remove=",remove=['${remove//';'/"','"}']"
fi fi
yunohost tools shell -c "from yunohost.permission import permission_urls; permission_urls('$app.$permission' ${add:-} ${remove:-})" yunohost tools shell -c "from yunohost.permission import permission_url; permission_url('$app.$permission', url=$url)"
} }
# Update a permission for the app # Update a permission for the app
# #
# usage: ynh_permission_update --permission "permission" --add "group" ["group" ...] --remove "group" ["group" ...] # usage: ynh_permission_update --permission "permission" --add "group" ["group" ...] --remove "group" ["group" ...]

View file

@ -53,9 +53,6 @@ do_pre_regen() {
else else
sudo cp services.yml /etc/yunohost/services.yml sudo cp services.yml /etc/yunohost/services.yml
fi fi
mkdir -p "$pending_dir"/etc/etckeeper/
cp etckeeper.conf "$pending_dir"/etc/etckeeper/
} }
_update_services() { _update_services() {

View file

@ -57,6 +57,12 @@ children:
objectClass: objectClass:
- posixGroup - posixGroup
- groupOfNamesYnh - groupOfNamesYnh
cn=visitors,ou=groups:
cn: visitors
gidNumber: "4003"
objectClass:
- posixGroup
- groupOfNamesYnh
depends_children: depends_children:
cn=mail.main,ou=permission: cn=mail.main,ou=permission:

View file

@ -63,7 +63,7 @@ bantime = 600
findtime = 600 findtime = 600
# "maxretry" is the number of failures before a host get banned. # "maxretry" is the number of failures before a host get banned.
maxretry = 5 maxretry = 10
# "backend" specifies the backend used to get files modification. # "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto". # Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".

View file

@ -29,4 +29,3 @@ protocol = tcp
filter = yunohost filter = yunohost
logpath = /var/log/nginx/*error.log logpath = /var/log/nginx/*error.log
/var/log/nginx/*access.log /var/log/nginx/*access.log
maxretry = 10

View file

@ -1,43 +0,0 @@
# The VCS to use.
#VCS="hg"
VCS="git"
#VCS="bzr"
#VCS="darcs"
# Options passed to git commit when run by etckeeper.
GIT_COMMIT_OPTIONS="--quiet"
# Options passed to hg commit when run by etckeeper.
HG_COMMIT_OPTIONS=""
# Options passed to bzr commit when run by etckeeper.
BZR_COMMIT_OPTIONS=""
# Options passed to darcs record when run by etckeeper.
DARCS_COMMIT_OPTIONS="-a"
# Uncomment to avoid etckeeper committing existing changes
# to /etc automatically once per day.
#AVOID_DAILY_AUTOCOMMITS=1
# Uncomment the following to avoid special file warning
# (the option is enabled automatically by cronjob regardless).
#AVOID_SPECIAL_FILE_WARNING=1
# Uncomment to avoid etckeeper committing existing changes to
# /etc before installation. It will cancel the installation,
# so you can commit the changes by hand.
#AVOID_COMMIT_BEFORE_INSTALL=1
# The high-level package manager that's being used.
# (apt, pacman-g2, yum, zypper etc)
HIGHLEVEL_PACKAGE_MANAGER=apt
# The low-level package manager that's being used.
# (dpkg, rpm, pacman, pacman-g2, etc)
LOWLEVEL_PACKAGE_MANAGER=dpkg
# To push each commit to a remote, put the name of the remote here.
# (eg, "origin" for git). Space-separated lists of multiple remotes
# also work (eg, "origin gitlab github" for git).
PUSH_REMOTE=""

76
debian/changelog vendored
View file

@ -1,3 +1,79 @@
yunohost (3.7.0.1) testing; urgency=low
- Hotfix to avoid having a shitload of warnings displayed during the permission migration
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 31 Oct 2019 20:35:00 +0000
yunohost (3.7.0) testing; urgency=low
# ~ Major stuff
- [enh] Add group and permission mechanism (YunoHost#585, YunoHost#763, YunoHost#789, YunoHost#790, YunoHost#795, YunoHost#797, SSOwat#147, Moulinette#189, YunoHost-admin#257)
- [mod] Rework migration system to have independent migrations (YunoHost#768, YunoHost#774, YunoHost-admin#258)
- [enh] Many improvements in the way app action failures are handled (YunoHost#769, YunoHost#811)
- [enh] Improve checks for system anomalies after app operations (YunoHost#785)
- [mod] Spookier warnings for dangerous app installs (YunoHost#814, Moulinette/808f620)
- [enh] Support app manifests in toml (YunoHost#748, Moulinette#204, Moulinette/55515cb)
- [mod] Get rid of etckeeper (YunoHost#803)
- [enh] Quite a lot of messages improvements, string cleaning, language rework... (YunoHost#793, YunoHost#799, YunoHost#823, SSOwat#143, YunoHost#766, YunoHost#767, YunoHost/fd99ef0, YunoHost/92a6315, YunoHost-admin/10ea04a, Moulinette/599bec3, Moulinette#208, Moulinette#213, Moulinette/b7d415d, Moulinette/a8966b8, Moulinette/fdf9a71, Moulinette/d895ae3, Moulinette/bdf0a1c, YunoHost#817, YunoHost#823, YunoHost/79627d7, YunoHost/9ee3d23, YunoHost-admin#265)
- [i18n] Improved translations for Catalan, Occitan, French, Esperanto, Arabic, German, Spanish, Norwegian Bokmål, Portuguese
# Smaller or pretty technical fix/enh
- [enh] Add unit/functional tests for apps + improve other tests (YunoHost#779, YunoHost#808)
- [enh] Preparations for moulinette Python3 migration (Tox, Pytest and unit tests) (Moulinette#203, Moulinette#206, Moulinette#207, Moulinette#210, Moulinette#211 Moulinette#212, Moulinette/2403ee1, Moulinette/69b0d49, Moulinette/49c749c, Moulinette/2c84ee1, Moulinette/cef72f7, YunoHost/6365a26)
- [enh] Support python hooks (YunoHost#747)
- [enh] Upgrade n version + compatibility with arm64 (YunoHost#753)
- [enh] Add OpenLDAP TLS support (YunoHost#755, YunoHost/0a2d1c7, YunoHost/2dc8095)
- [enh] Improve PostgreSQL password security (YunoHost#762)
- [enh] Integrate actions/config-panel into operation logs (YunoHost#764)
- [mod] Assume that apps without any 'path' setting defined aren't webapps (YunoHost#765)
- [fix] Set dpkg vendor to YunoHost (YunoHost#749, YunoHost#772)
- [enh] Adding variable 'token' to data to redact from logs (YunoHost#783)
- [enh] Add --force and --dry-run options to 'yunohost dyndns update' (YunoHost#786)
- [fix] Don't throw a fatal error if we can't change the hostname (YunoHost/fe3ecd7)
- [enh] Dynamically evaluate proper mariadb-server-<version> (YunoHost/f0440fb)
- [fix] Bad format for backup info.json ... (YunoHost/7d0119a)
- [fix] Inline buttons responsiveness on migration screen (YunoHost-admin#259)
- [enh] Add debug logs to SSOwat (SSOwat#145)
- [enh] Add a write_to_yaml utility similar to write_to_json (Moulinette/2e2e627)
- [enh] Warn the user about long locks (Moulinette#205)
- [mod] Tweak stuff about setuptools and moulinette deps? (Moulinette/b739f27, Moulinette/da00fc9, Moulinette/d8cbbb0)
- [fix] Misc micro bugfixes or improvements (YunoHost#743, YunoHost#792, YunoHost/6f48d1d, YunoHost/d516cf8, YunoHost#819, Moulinette/83d9e77, YunoHost/63d364e, YunoHost/68e9724, YunoHost/0849adb, YunoHost/19dbe87, YunoHost/61931f2, YunoHost/6dc720f, YunoHost/4def4df, SSOwat#140, SSOwat#141, YunoHost#829)
- [doc] Fix doc building + add doc build tests with Tox (Moulinette/f1ac5b8, Moulinette/df7d478, Moulinette/74c8f79, Moulinette/bcf92c7, Moulinette/af2c80c, Moulinette/d52a574, Moulinette/307f660, Moulinette/dced104, Moulinette/ed3823b)
- [enh] READMEs improvements (YunoHost/b3398e7, SSOwat/ee67b6f, Moulinette/1541b74, Moulinette/ad1eeef, YunoHost/25afdd4, YunoHost/73741f6)
Thanks to all contributors <3 ! (accross all repo: Yunohost, Moulinette, SSOwat, Yunohost-admin) : advocatux, Aksel K., Aleks, Allan N., amirale qt, Armin P., Bram, ButterflyOfFire, Carles S. A., chema o. r., decentral1se, Emmanuel V., Etienne M., Filip B., Geoff M., htsr, Jibec, Josué, Julien J., Kayou, liberodark, ljf, lucaskev, Lukas D., madtibo, Martin D., Mélanie C., nr 458 h, pitfd, ppr, Quentí, sidddy, troll, tufek yamero, xaloc33, yalh76
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 31 Oct 2019 18:00:00 +0000
yunohost (3.6.5.3) stable; urgency=low
- [fix] More general grep for the php/sury dependency nightmare fix (followup of #809)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 29 Oct 2019 03:48:00 +0000
yunohost (3.6.5.2) stable; urgency=low
- [fix] Alex was drunk and released an epic stupid bug in stable (2623d385)
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 10 Oct 2019 01:00:00 +0000
yunohost (3.6.5.1) stable; urgency=low
- [mod] Change maxretry of fail2ban from 6 to 10 (fe8fd1b)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 08 Oct 2019 20:00:00 +0000
yunohost (3.6.5) stable; urgency=low
- [enh] Detect and warn early about unavailable full domains... (#798)
- [mod] Change maxretry of fail2ban from 6 to 10 (#802)
- [fix] Epicly ugly workaround for the goddamn dependency nighmare about sury fucking up php7.0 dependencies (#809)
- [fix] Support logfiles not ending with .log in logrotate ... (#810)
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 08 Oct 2019 19:00:00 +0000
yunohost (3.6.4.6) stable; urgency=low yunohost (3.6.4.6) stable; urgency=low
- [fix] Hopefully fix the issue about corrupted logs metadata files (d507d447, 1cec9d78) - [fix] Hopefully fix the issue about corrupted logs metadata files (d507d447, 1cec9d78)

4
debian/control vendored
View file

@ -17,7 +17,7 @@ Depends: ${python:Depends}, ${misc:Depends}
, python-toml , python-toml
, glances, apt-transport-https , glances, apt-transport-https
, dnsutils, bind9utils, unzip, git, curl, cron, wget, jq , dnsutils, bind9utils, unzip, git, curl, cron, wget, jq
, ca-certificates, netcat-openbsd, iproute , ca-certificates, netcat-openbsd, iproute2
, mariadb-server, php-mysql | php-mysqlnd , mariadb-server, php-mysql | php-mysqlnd
, slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd , slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd
, postfix-ldap, postfix-policyd-spf-perl, postfix-pcre, procmail, mailutils, postsrsd , postfix-ldap, postfix-policyd-spf-perl, postfix-pcre, procmail, mailutils, postsrsd
@ -31,7 +31,7 @@ Depends: ${python:Depends}, ${misc:Depends}
, equivs, lsof , equivs, lsof
Recommends: yunohost-admin Recommends: yunohost-admin
, openssh-server, ntp, inetutils-ping | iputils-ping , openssh-server, ntp, inetutils-ping | iputils-ping
, bash-completion, rsyslog, etckeeper , bash-completion, rsyslog
, php-gd, php-curl, php-gettext, php-mcrypt , php-gd, php-curl, php-gettext, php-mcrypt
, python-pip , python-pip
, unattended-upgrades , unattended-upgrades

View file

@ -1,31 +1,31 @@
{ {
"action_invalid": "Acció '{action:s}' invàlida", "action_invalid": "Acció '{action:s}' invàlida",
"admin_password": "Contrasenya d'administració", "admin_password": "Contrasenya d'administració",
"admin_password_change_failed": "No s'ha pogut canviar la contrasenya", "admin_password_change_failed": "No es pot canviar la contrasenya",
"admin_password_changed": "S'ha canviat la contrasenya d'administració", "admin_password_changed": "S'ha canviat la contrasenya d'administració",
"app_already_installed": "{app:s} ja està instal·lada", "app_already_installed": "{app:s} ja està instal·lada",
"app_already_installed_cant_change_url": "Aquesta aplicació ja està instal·lada. La URL no és pot canviar únicament amb aquesta funció. Mireu a \"app changeurl\" si està disponible.", "app_already_installed_cant_change_url": "Aquesta aplicació ja està instal·lada. La URL no és pot canviar únicament amb aquesta funció. Mireu a \"app changeurl\" si està disponible.",
"app_already_up_to_date": "{app:s} ja està actualitzada", "app_already_up_to_date": "{app:s} ja està actualitzada",
"app_argument_choice_invalid": "Aquesta opció no és vàlida per l'argument '{name:s}', ha de ser una de {choices:s}", "app_argument_choice_invalid": "Utilitzeu una de les opcions «{choices:s}» per l'argument «{name:s}»",
"app_argument_invalid": "Valor invàlid per l'argument '{name:s}':{error:s}", "app_argument_invalid": "Escolliu un valor vàlid per l'argument «{name:s}»: {error:s}",
"app_argument_required": "Es necessita l'argument '{name:s}'", "app_argument_required": "Es necessita l'argument '{name:s}'",
"app_change_no_change_url_script": "L'aplicació {app_name:s} encara no permet canviar la seva URL, es possible que s'hagi d'actualitzar.", "app_change_no_change_url_script": "L'aplicació {app_name:s} encara no permet canviar la seva URL, es possible que s'hagi d'actualitzar.",
"app_change_url_failed_nginx_reload": "No s'ha pogut tornar a carregar nginx. Aquí teniu el resultat de \"nginx -t\":\n{nginx_errors:s}", "app_change_url_failed_nginx_reload": "No s'ha pogut tornar a carregar NGINX. Aquí teniu el resultat de \"nginx -t\":\n{nginx_errors:s}",
"app_change_url_identical_domains": "L'antic i el nou domini/camí són idèntics ('{domain:s}{path:s}'), no hi ha res per fer.", "app_change_url_identical_domains": "L'antic i el nou domini/camí són idèntics ('{domain:s}{path:s}'), no hi ha res per fer.",
"app_change_url_no_script": "Aquesta aplicació '{app_name:s}' encara no permet modificar la URL. Potser s'ha d'actualitzar l'aplicació.", "app_change_url_no_script": "L'aplicació '{app_name:s}' encara no permet modificar la URL. Potser s'ha d'actualitzar.",
"app_change_url_success": "La URL de {app:s} s'ha canviat correctament a {domain:s}{path:s}", "app_change_url_success": "La URL de {app:s} ara és {domain:s}{path:s}",
"app_extraction_failed": "No s'han pogut extreure els fitxers d'instal·lació", "app_extraction_failed": "No s'han pogut extreure els fitxers d'instal·lació",
"app_id_invalid": "Id de l'aplicació incorrecte", "app_id_invalid": "ID de l'aplicació incorrecte",
"app_incompatible": "L'aplicació {app} no és compatible amb la teva versió de YunoHost", "app_incompatible": "L'aplicació {app} no és compatible amb la teva versió de YunoHost",
"app_install_files_invalid": "Fitxers d'instal·lació invàlids", "app_install_files_invalid": "Aquests fitxers no es poden instal·lar",
"app_location_already_used": "L'aplicació '{app}' ja està instal·lada en aquest camí ({path})", "app_location_already_used": "L'aplicació «{app}» ja està instal·lada en ({path})",
"app_make_default_location_already_used": "No es pot fer l'aplicació '{app}' per defecte en el domini {domain} ja que ja és utilitzat per una altra aplicació '{other_app}'", "app_make_default_location_already_used": "No es pot fer l'aplicació '{app}' per defecte en el domini «{domain}» ja que ja és utilitzat per una altra aplicació '{other_app}'",
"app_location_install_failed": "No s'ha pogut instal·lar l'aplicació en aquest camí ja que entra en conflicte amb l'aplicació '{other_app}' ja instal·lada a '{other_path}'", "app_location_install_failed": "No s'ha pogut instal·lar l'aplicació aquí ja que entra en conflicte amb l'aplicació «{other_app}» ja instal·lada a «{other_path}»",
"app_location_unavailable": "Aquesta url no està disponible o entra en conflicte amb aplicacions ja instal·lades:\n{apps:s}", "app_location_unavailable": "Aquesta URL no està disponible o entra en conflicte amb aplicacions ja instal·lades:\n{apps:s}",
"app_manifest_invalid": "Manifest d'aplicació incorrecte: {error}", "app_manifest_invalid": "Hi ha algun error amb el manifest de l'aplicació: {error}",
"app_no_upgrade": "No hi ha cap aplicació per actualitzar", "app_no_upgrade": "No hi ha cap aplicació per actualitzar",
"app_not_correctly_installed": "{app:s} sembla estar mal instal·lada", "app_not_correctly_installed": "{app:s} sembla estar mal instal·lada",
"app_not_installed": "L'aplicació «{app:s}» no està instal·lada. Aquí hi ha la llista d'aplicacions instal·lades: {all_apps}", "app_not_installed": "No s'ha trobat l'aplicació «{app:s}» en la llista d'aplicacions instal·lades: {all_apps}",
"app_not_properly_removed": "{app:s} no s'ha pogut suprimir correctament", "app_not_properly_removed": "{app:s} no s'ha pogut suprimir correctament",
"app_package_need_update": "El paquet de l'aplicació {app} ha de ser actualitzat per poder seguir els canvis de YunoHost", "app_package_need_update": "El paquet de l'aplicació {app} ha de ser actualitzat per poder seguir els canvis de YunoHost",
"app_removed": "{app:s} ha estat suprimida", "app_removed": "{app:s} ha estat suprimida",
@ -35,22 +35,22 @@
"app_sources_fetch_failed": "No s'han pogut carregar els fitxers font, l'URL és correcta?", "app_sources_fetch_failed": "No s'han pogut carregar els fitxers font, l'URL és correcta?",
"app_unknown": "Aplicació desconeguda", "app_unknown": "Aplicació desconeguda",
"app_unsupported_remote_type": "El tipus remot utilitzat per l'aplicació no està suportat", "app_unsupported_remote_type": "El tipus remot utilitzat per l'aplicació no està suportat",
"app_upgrade_app_name": "Actualitzant l'aplicació {app}…", "app_upgrade_app_name": "Actualitzant {app}…",
"app_upgrade_failed": "No s'ha pogut actualitzar {app:s}", "app_upgrade_failed": "No s'ha pogut actualitzar {app:s}",
"app_upgrade_some_app_failed": "No s'han pogut actualitzar algunes aplicacions", "app_upgrade_some_app_failed": "No s'han pogut actualitzar algunes aplicacions",
"app_upgraded": "{app:s} ha estat actualitzada", "app_upgraded": "S'ha actualitzat {app:s}",
"appslist_corrupted_json": "No s'han pogut carregar les llistes d'aplicacions. Sembla que {filename:s} està danyat.", "appslist_corrupted_json": "No s'han pogut carregar les llistes d'aplicacions. Sembla que {filename:s} està danyat.",
"appslist_could_not_migrate": "No s'ha pogut migrar la llista d'aplicacions {appslist:s}! No s'ha pogut analitzar la URL... L'antic cronjob s'ha guardat a {bkp_file:s}.", "appslist_could_not_migrate": "No s'ha pogut migrar la llista d'aplicacions «{appslist:s}»! No s'ha pogut analitzar la URL... L'antic cronjob s'ha guardat a {bkp_file:s}.",
"appslist_fetched": "S'ha descarregat la llista d'aplicacions {appslist:s} correctament", "appslist_fetched": "S'ha actualitzat la llista d'aplicacions «{appslist:s}»",
"appslist_migrating": "Migrant la llista d'aplicacions {appslist:s}…", "appslist_migrating": "Migrant la llista d'aplicacions «{appslist:s}»…",
"appslist_name_already_tracked": "Ja hi ha una llista d'aplicacions registrada amb el nom {name:s}.", "appslist_name_already_tracked": "Ja hi ha una llista d'aplicacions registrada amb el nom {name:s}.",
"appslist_removed": "S'ha eliminat la llista d'aplicacions {appslist:s}", "appslist_removed": "S'ha eliminat la llista d'aplicacions «{appslist:s}»",
"appslist_retrieve_bad_format": "L'arxiu obtingut per la llista d'aplicacions {appslist:s} no és vàlid", "appslist_retrieve_bad_format": "No s'ha pogut llegir la llista d'aplicacions obtinguda «{appslist:s}»",
"appslist_retrieve_error": "No s'ha pogut obtenir la llista d'aplicacions remota {appslist:s}: {error:s}", "appslist_retrieve_error": "No s'ha pogut obtenir la llista d'aplicacions remota «{appslist:s}»: {error:s}",
"appslist_unknown": "La llista d'aplicacions {appslist:s} es desconeguda.", "appslist_unknown": "La llista d'aplicacions «{appslist:s}» es desconeguda.",
"appslist_url_already_tracked": "Ja hi ha una llista d'aplicacions registrada amb al URL {url:s}.", "appslist_url_already_tracked": "Ja hi ha una llista d'aplicacions registrada amb al URL {url:s}.",
"ask_current_admin_password": "Contrasenya d'administrador actual", "ask_current_admin_password": "Contrasenya d'administrador actual",
"ask_email": "Correu electrònic", "ask_email": "Adreça de correu electrònic",
"ask_firstname": "Nom", "ask_firstname": "Nom",
"ask_lastname": "Cognom", "ask_lastname": "Cognom",
"ask_list_to_remove": "Llista per a suprimir", "ask_list_to_remove": "Llista per a suprimir",
@ -58,54 +58,54 @@
"ask_new_admin_password": "Nova contrasenya d'administrador", "ask_new_admin_password": "Nova contrasenya d'administrador",
"ask_password": "Contrasenya", "ask_password": "Contrasenya",
"ask_path": "Camí", "ask_path": "Camí",
"backup_abstract_method": "Encara no s'ha implementat aquest mètode de copia de seguretat", "backup_abstract_method": "Encara està per implementar aquest mètode de còpia de seguretat",
"backup_action_required": "S'ha d'especificar què s'ha de guardar", "backup_action_required": "S'ha d'especificar què s'ha de guardar",
"backup_app_failed": "No s'ha pogut fer la còpia de seguretat de l'aplicació \"{app:s}\"", "backup_app_failed": "No s'ha pogut fer la còpia de seguretat de l'aplicació \"{app:s}\"",
"backup_applying_method_borg": "Enviant tots els fitxers de la còpia de seguretat al repositori borg-backup…", "backup_applying_method_borg": "Enviant tots els fitxers de la còpia de seguretat al repositori borg-backup…",
"backup_applying_method_copy": "Còpia de tots els fitxers a la còpia de seguretat…", "backup_applying_method_copy": "Còpia de tots els fitxers a la còpia de seguretat…",
"backup_applying_method_custom": "Crida del mètode de còpia de seguretat personalitzat \"{method:s}\"…", "backup_applying_method_custom": "Crida del mètode de còpia de seguretat personalitzat \"{method:s}\"…",
"backup_applying_method_tar": "Creació de l'arxiu tar de la còpia de seguretat…", "backup_applying_method_tar": "Creació de l'arxiu TAR de la còpia de seguretat…",
"backup_archive_app_not_found": "L'aplicació \"{app:s}\" no es troba dins l'arxiu de la còpia de seguretat", "backup_archive_app_not_found": "No s'ha pogut trobar l'aplicació «{app:s}» dins l'arxiu de la còpia de seguretat",
"backup_archive_broken_link": "No s'ha pogut accedir a l'arxiu de la còpia de seguretat (enllaç invàlid cap a {path:s})", "backup_archive_broken_link": "No s'ha pogut accedir a l'arxiu de la còpia de seguretat (enllaç invàlid cap a {path:s})",
"backup_archive_mount_failed": "No s'ha pogut carregar l'arxiu de la còpia de seguretat", "backup_archive_mount_failed": "No s'ha pogut carregar l'arxiu de la còpia de seguretat",
"backup_archive_name_exists": "Ja hi ha una còpia de seguretat amb aquest nom", "backup_archive_name_exists": "Ja hi ha una còpia de seguretat amb aquest nom.",
"backup_archive_name_unknown": "Còpia de seguretat local \"{name:s}\" desconeguda", "backup_archive_name_unknown": "Còpia de seguretat local \"{name:s}\" desconeguda",
"backup_archive_open_failed": "No s'ha pogut obrir l'arxiu de la còpia de seguretat", "backup_archive_open_failed": "No s'ha pogut obrir l'arxiu de la còpia de seguretat",
"backup_archive_system_part_not_available": "La part \"{part:s}\" del sistema no està disponible en aquesta copia de seguretat", "backup_archive_system_part_not_available": "La part «{part:s}» del sistema no està disponible en aquesta copia de seguretat",
"backup_archive_writing_error": "No es poden afegir arxius a l'arxiu comprimit de la còpia de seguretat", "backup_archive_writing_error": "No es poden afegir els arxius «{source:s}» (anomenats en l'arxiu «{dest:s}») a l'arxiu comprimit de la còpia de seguretat «{archive:s}»",
"backup_ask_for_copying_if_needed": "Alguns fitxers no s'han pogut preparar per la còpia de seguretat utilitzant el mètode que evita malgastar espai del sistema temporalment. Per fer la còpia de seguretat, s'han d'utilitzar {size:s}MB temporalment. Hi esteu d'acord?", "backup_ask_for_copying_if_needed": "Voleu fer la còpia de seguretat utilitzant {size:s} MB temporalment? (S'utilitza aquest mètode ja que alguns dels fitxers no s'han pogut preparar utilitzar un mètode més eficient.)",
"backup_borg_not_implemented": "El mètode de còpia de seguretat Borg encara no està implementat", "backup_borg_not_implemented": "El mètode de còpia de seguretat Borg encara no està implementat",
"backup_cant_mount_uncompress_archive": "No es pot carregar en mode de lectura només el directori de l'arxiu descomprimit", "backup_cant_mount_uncompress_archive": "No es pot carregar l'arxiu descomprimit com a protegit contra escriptura",
"backup_cleaning_failed": "No s'ha pogut netejar el directori temporal de la còpia de seguretat", "backup_cleaning_failed": "No s'ha pogut netejar el directori temporal de la còpia de seguretat",
"backup_copying_to_organize_the_archive": "Copiant {size:s}MB per organitzar l'arxiu", "backup_copying_to_organize_the_archive": "Copiant {size:s}MB per organitzar l'arxiu",
"backup_couldnt_bind": "No es pot lligar {src:s} amb {dest:s}.", "backup_couldnt_bind": "No es pot lligar {src:s} amb {dest:s}.",
"backup_created": "S'ha creat la còpia de seguretat", "backup_created": "S'ha creat la còpia de seguretat",
"backup_creating_archive": "Creant l'arxiu de la còpia de seguretat…", "backup_creating_archive": "Creant l'arxiu de la còpia de seguretat…",
"aborting": "Avortant.", "aborting": "Avortant.",
"app_not_upgraded": "Les següents aplicacions no s'han actualitzat: {apps}", "app_not_upgraded": "L'aplicació «{failed_app}» no s'ha pogut actualitzar, i com a conseqüència l'actualització de les següents aplicacions ha estat cancel·lada: {apps}",
"app_start_install": "instal·lant l'aplicació {app}…", "app_start_install": "instal·lant l'aplicació «{app}»…",
"app_start_remove": "Eliminant l'aplicació {app}…", "app_start_remove": "Eliminant l'aplicació «{app}»…",
"app_start_backup": "Recuperant els fitxers pels que s'ha de fer una còpia de seguretat per {app}…", "app_start_backup": "Recuperant els fitxers pels que s'ha de fer una còpia de seguretat per «{app}»…",
"app_start_restore": "Recuperant l'aplicació {app}…", "app_start_restore": "Recuperant l'aplicació «{app}»…",
"app_upgrade_several_apps": "S'actualitzaran les següents aplicacions: {apps}", "app_upgrade_several_apps": "S'actualitzaran les següents aplicacions: {apps}",
"ask_new_domain": "Nou domini", "ask_new_domain": "Nou domini",
"ask_new_path": "Nou camí", "ask_new_path": "Nou camí",
"backup_actually_backuping": "S'està creant un arxiu de còpia de seguretat a partir dels fitxers recuperats…", "backup_actually_backuping": "Creant un arxiu de còpia de seguretat a partir dels fitxers recuperats…",
"backup_creation_failed": "Ha fallat la creació de la còpia de seguretat", "backup_creation_failed": "No s'ha pogut crear l'arxiu de la còpia de seguretat",
"backup_csv_addition_failed": "No s'han pogut afegir fitxers per a fer-ne la còpia de seguretat al fitxer CSV", "backup_csv_addition_failed": "No s'han pogut afegir fitxers per a fer-ne la còpia de seguretat al fitxer CSV",
"backup_csv_creation_failed": "No s'ha pogut crear el fitxer CSV necessari per a futures operacions de recuperació", "backup_csv_creation_failed": "No s'ha pogut crear el fitxer CSV necessari per a la restauració",
"backup_custom_backup_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa \"backup\"", "backup_custom_backup_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa «backup»",
"backup_custom_mount_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa \"mount\"", "backup_custom_mount_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa «mount»",
"backup_custom_need_mount_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa \"need_mount\"", "backup_custom_need_mount_error": "El mètode de còpia de seguretat personalitzat ha fallat a l'etapa \"need_mount\"",
"backup_delete_error": "No s'ha pogut suprimir \"{path:s}\"", "backup_delete_error": "No s'ha pogut suprimir «{path:s}»",
"backup_deleted": "S'ha suprimit la còpia de seguretat", "backup_deleted": "S'ha suprimit la còpia de seguretat",
"backup_extracting_archive": "Extraient l'arxiu de la còpia de seguretat…", "backup_extracting_archive": "Extraient l'arxiu de la còpia de seguretat…",
"backup_hook_unknown": "Script de còpia de seguretat \"{hook:s}\" desconegut", "backup_hook_unknown": "Script de còpia de seguretat «{hook:s}» desconegut",
"backup_invalid_archive": "Arxiu de còpia de seguretat no vàlid", "backup_invalid_archive": "Aquest no és un arxiu de còpia de seguretat",
"backup_method_borg_finished": "La còpia de seguretat a borg ha acabat", "backup_method_borg_finished": "La còpia de seguretat a Borg ha acabat",
"backup_method_copy_finished": "La còpia de la còpia de seguretat ha acabat", "backup_method_copy_finished": "La còpia de la còpia de seguretat ha acabat",
"backup_method_custom_finished": "El mètode de còpia de seguretat personalitzat \"{method:s}\" ha acabat", "backup_method_custom_finished": "El mètode de còpia de seguretat personalitzat \"{method:s}\" ha acabat",
"backup_method_tar_finished": "S'ha creat l'arxiu de còpia de seguretat tar", "backup_method_tar_finished": "S'ha creat l'arxiu de còpia de seguretat TAR",
"backup_mount_archive_for_restore": "Preparant l'arxiu per la restauració…", "backup_mount_archive_for_restore": "Preparant l'arxiu per la restauració…",
"good_practices_about_user_password": "Esteu a punt de definir una nova contrasenya d'usuari. La contrasenya ha de tenir un mínim de 8 caràcters; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials).", "good_practices_about_user_password": "Esteu a punt de definir una nova contrasenya d'usuari. La contrasenya ha de tenir un mínim de 8 caràcters; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials).",
"password_listed": "Aquesta contrasenya és una de les més utilitzades en el món. Si us plau utilitzeu-ne una més única.", "password_listed": "Aquesta contrasenya és una de les més utilitzades en el món. Si us plau utilitzeu-ne una més única.",
@ -115,42 +115,42 @@
"password_too_simple_4": "La contrasenya ha de tenir un mínim de 12 caràcters i tenir dígits, majúscules, minúscules i caràcters especials", "password_too_simple_4": "La contrasenya ha de tenir un mínim de 12 caràcters i tenir dígits, majúscules, minúscules i caràcters especials",
"backup_no_uncompress_archive_dir": "El directori de l'arxiu descomprimit no existeix", "backup_no_uncompress_archive_dir": "El directori de l'arxiu descomprimit no existeix",
"backup_nothings_done": "No hi ha res a guardar", "backup_nothings_done": "No hi ha res a guardar",
"backup_output_directory_forbidden": "Directori de sortida no permès. Les còpies de seguretat no es poden crear ni dins els directoris /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var ni dins els subdirectoris /home/yunohost.backup/archives", "backup_output_directory_forbidden": "Escolliu un directori de sortida different. Les còpies de seguretat no es poden crear ni dins els directoris /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var ni dins els subdirectoris /home/yunohost.backup/archives",
"backup_output_directory_not_empty": "El directori de sortida no està buit", "backup_output_directory_not_empty": "Heu d'escollir un directori de sortida buit",
"backup_output_directory_required": "Heu d'especificar un directori de sortida per la còpia de seguretat", "backup_output_directory_required": "Heu d'especificar un directori de sortida per la còpia de seguretat",
"backup_output_symlink_dir_broken": "Teniu un enllaç simbòlic trencat en lloc del directori dels arxius '{path:s}'. Pot ser teniu una configuració per la còpia de seguretat específica en un altre sistema de fitxers, si és el cas segurament heu oblidat muntar o connectar el disc dur o la clau USB.", "backup_output_symlink_dir_broken": "El directori del arxiu «{path:s}» es un enllaç simbòlic trencat. Pot ser heu oblidat muntar, tornar a muntar o connectar el mitja d'emmagatzematge al que apunta.",
"backup_php5_to_php7_migration_may_fail": "No s'ha pogut convertir l'arxiu per suportar php7, la restauració de les vostres aplicacions pot fallar (raó: {error:s})", "backup_php5_to_php7_migration_may_fail": "No s'ha pogut convertir l'arxiu per suportar PHP 7, pot ser que no es puguin restaurar les vostres aplicacions PHP (raó: {error:s})",
"backup_running_hooks": "Executant els scripts de la còpia de seguretat…", "backup_running_hooks": "Executant els scripts de la còpia de seguretat…",
"backup_system_part_failed": "No s'ha pogut fer la còpia de seguretat de la part \"{part:s}\" del sistema", "backup_system_part_failed": "No s'ha pogut fer la còpia de seguretat de la part \"{part:s}\" del sistema",
"backup_unable_to_organize_files": "No s'han pogut organitzar els fitxers dins de l'arxiu amb el mètode ràpid", "backup_unable_to_organize_files": "No s'ha pogut utilitzar el mètode ràpid per organitzar els fitxers dins de l'arxiu",
"backup_with_no_backup_script_for_app": "L'aplicació {app:s} no té un script de còpia de seguretat. Serà ignorat.", "backup_with_no_backup_script_for_app": "L'aplicació «{app:s}» no té un script de còpia de seguretat. Serà ignorat.",
"backup_with_no_restore_script_for_app": "L'aplicació {app:s} no té un script de restauració, no podreu restaurar automàticament la còpia de seguretat d'aquesta aplicació.", "backup_with_no_restore_script_for_app": "L'aplicació «{app:s}» no té un script de restauració, no podreu restaurar automàticament la còpia de seguretat d'aquesta aplicació.",
"certmanager_acme_not_configured_for_domain": "El certificat pel domini {domain:s} sembla que no està instal·lat correctament. Si us plau executeu primer cert-install per aquest domini.", "certmanager_acme_not_configured_for_domain": "El certificat pel domini «{domain:s}» sembla que no està instal·lat correctament. Si us plau executeu primer «cert-install» per aquest domini.",
"certmanager_attempt_to_renew_nonLE_cert": "El certificat pel domini {domain:s} no ha estat emès per Let's Encrypt. No es pot renovar automàticament!", "certmanager_attempt_to_renew_nonLE_cert": "El certificat pel domini «{domain:s}» no ha estat emès per Let's Encrypt. No es pot renovar automàticament!",
"certmanager_attempt_to_renew_valid_cert": "El certificat pel domini {domain:s} està a punt de caducar! (Utilitzeu --force si sabeu el que esteu fent)", "certmanager_attempt_to_renew_valid_cert": "El certificat pel domini «{domain:s}» està a punt de caducar! (Utilitzeu --force si sabeu el que esteu fent)",
"certmanager_attempt_to_replace_valid_cert": "Esteu intentant sobreescriure un certificat correcte i vàlid pel domini {domain:s}! (Utilitzeu --force per ometre)", "certmanager_attempt_to_replace_valid_cert": "Esteu intentant sobreescriure un certificat correcte i vàlid pel domini {domain:s}! (Utilitzeu --force per ometre)",
"certmanager_cannot_read_cert": "S'ha produït un error al intentar obrir el certificat actual pel domini {domain:s} (arxiu: {file:s}), raó: {reason:s}", "certmanager_cannot_read_cert": "S'ha produït un error al intentar obrir el certificat actual pel domini {domain:s} (arxiu: {file:s}), raó: {reason:s}",
"certmanager_cert_install_success": "S'ha instal·lat correctament un certificat Let's Encrypt pel domini {domain:s}!", "certmanager_cert_install_success": "S'ha instal·lat correctament un certificat Let's Encrypt pel domini «{domain:s}»",
"certmanager_cert_install_success_selfsigned": "S'ha instal·lat correctament un certificat auto-signat pel domini {domain:s}!", "certmanager_cert_install_success_selfsigned": "S'ha instal·lat correctament un certificat auto-signat pel domini «{domain:s}»",
"certmanager_cert_renew_success": "S'ha renovat correctament el certificat Let's Encrypt pel domini {domain:s}!", "certmanager_cert_renew_success": "S'ha renovat correctament el certificat Let's Encrypt pel domini «{domain:s}»",
"certmanager_cert_signing_failed": "No s'ha pogut firmar el nou certificat", "certmanager_cert_signing_failed": "No s'ha pogut firmar el nou certificat",
"certmanager_certificate_fetching_or_enabling_failed": "Sembla que l'activació del nou certificat per {domain:s} ha fallat…", "certmanager_certificate_fetching_or_enabling_failed": "Sembla que utilitzar el nou certificat per {domain:s} ha fallat…",
"certmanager_conflicting_nginx_file": "No s'ha pogut preparar el domini per al desafiament ACME: l'arxiu de configuració nginx {filepath:s} entra en conflicte i s'ha d'eliminar primer", "certmanager_conflicting_nginx_file": "No s'ha pogut preparar el domini per al desafiament ACME: l'arxiu de configuració NGINX {filepath:s} entra en conflicte i s'ha d'eliminar primer",
"certmanager_couldnt_fetch_intermediate_cert": "S'ha exhaurit el temps d'esperar al intentar recollir el certificat intermedi des de Let's Encrypt. La instal·lació/renovació del certificat s'ha cancel·lat - torneu a intentar-ho més tard.", "certmanager_couldnt_fetch_intermediate_cert": "S'ha exhaurit el temps d'esperar al intentar recollir el certificat intermedi des de Let's Encrypt. La instal·lació/renovació del certificat s'ha cancel·lat - torneu a intentar-ho més tard.",
"certmanager_domain_cert_not_selfsigned": "El certificat pel domini {domain:s} no és auto-signat Esteu segur de voler canviar-lo? (Utilitzeu --force per fer-ho)", "certmanager_domain_cert_not_selfsigned": "El certificat pel domini {domain:s} no és auto-signat Esteu segur de voler canviar-lo? (Utilitzeu «--force» per fer-ho)",
"certmanager_domain_dns_ip_differs_from_public_ip": "El registre DNS \"A\" pel domini {domain:s} és diferent a l'adreça IP d'aquest servidor. Si heu modificat recentment el registre A, si us plau espereu a que es propagui (hi ha eines per verificar la propagació disponibles a internet). (Si sabeu el que esteu fent, podeu utilitzar --no-checks per desactivar aquestes comprovacions.)", "certmanager_domain_dns_ip_differs_from_public_ip": "El registre DNS \"A\" pel domini «{domain:s}» és diferent a l'adreça IP d'aquest servidor. Si heu modificat recentment el registre A, si us plau espereu a que es propagui (hi ha eines per verificar la propagació disponibles a internet). (Si sabeu el que esteu fent, podeu utilitzar «--no-checks» per desactivar aquestes comprovacions.)",
"certmanager_domain_http_not_working": "Sembla que el domini {domain:s} no és accessible via HTTP. Si us plau verifiqueu que les configuracions DNS i nginx siguin correctes", "certmanager_domain_http_not_working": "Sembla que el domini {domain:s} no és accessible via HTTP. Verifiqueu que les configuracions DNS i NGINX siguin correctes",
"certmanager_domain_not_resolved_locally": "El domini {domain:s} no es pot resoldre dins del vostre servidor YunoHost. Això pot passar si heu modificat recentment el registre DNS. Si és així, si us plau espereu unes hores per a que es propagui. Si el problema continua, considereu afegir {domain:s} a /etc/hosts. (Si sabeu el que esteu fent, podeu utilitzar --no-checks per desactivar aquestes comprovacions.)", "certmanager_domain_not_resolved_locally": "El domini {domain:s} no es pot resoldre dins del vostre servidor YunoHost. Això pot passar si heu modificat recentment el registre DNS. Si és així, si us plau espereu unes hores per a que es propagui. Si el problema continua, considereu afegir {domain:s} a /etc/hosts. (Si sabeu el que esteu fent, podeu utilitzar --no-checks per desactivar aquestes comprovacions.)",
"certmanager_domain_unknown": "Domini desconegut {domain:s}", "certmanager_domain_unknown": "Domini desconegut «{domain:s}»",
"certmanager_error_no_A_record": "No s'ha trobat cap registre DNS \"A\" per {domain:s}. Heu de fer que el vostre nom de domini apunti cap a la vostra màquina per tal de poder instal·lar un certificat Let's Encrypt! (Si sabeu el que esteu fent, podeu utilitzar --no-checks per desactivar aquestes comprovacions.)", "certmanager_error_no_A_record": "No s'ha trobat cap registre DNS «A» per «{domain:s}». Heu de fer que el vostre nom de domini apunti cap a la vostra màquina per tal de poder instal·lar un certificat Let's Encrypt. (Si sabeu el que esteu fent, podeu utilitzar «--no-checks» per desactivar aquestes comprovacions.)",
"certmanager_hit_rate_limit": "S'han emès massa certificats recentment per aquest mateix conjunt de dominis {domain:s}. Si us plau torneu-ho a intentar més tard. Consulteu https://letsencrypt.org/docs/rate-limits/ per obtenir més detalls", "certmanager_hit_rate_limit": "S'han emès massa certificats recentment per aquest mateix conjunt de dominis {domain:s}. Si us plau torneu-ho a intentar més tard. Consulteu https://letsencrypt.org/docs/rate-limits/ per obtenir més detalls",
"certmanager_http_check_timeout": "S'ha exhaurit el temps d'espera quan el servidor ha intentat contactar amb ell mateix via HTTP utilitzant la seva adreça IP pública (domini domain:s} amb IP {ip:s}). Pot ser degut a hairpinning o a que el talla focs/router al que està connectat el servidor estan mal configurats.", "certmanager_http_check_timeout": "S'ha exhaurit el temps d'espera quan el servidor ha intentat contactar amb ell mateix via HTTP utilitzant la seva adreça IP pública (domini «{domain:s}» amb IP «{ip:s}»). Pot ser degut a hairpinning o a que el talla focs/router al que està connectat el servidor estan mal configurats.",
"certmanager_no_cert_file": "No s'ha pogut llegir l'arxiu del certificat pel domini {domain:s} (fitxer: {file:s})", "certmanager_no_cert_file": "No s'ha pogut llegir l'arxiu del certificat pel domini {domain:s} (fitxer: {file:s})",
"certmanager_self_ca_conf_file_not_found": "No s'ha trobat el fitxer de configuració per l'autoritat del certificat auto-signat (fitxer: {file:s})", "certmanager_self_ca_conf_file_not_found": "No s'ha trobat el fitxer de configuració per l'autoritat del certificat auto-signat (fitxer: {file:s})",
"certmanager_unable_to_parse_self_CA_name": "No s'ha pogut analitzar el nom de l'autoritat del certificat auto-signat (fitxer: {file:s})", "certmanager_unable_to_parse_self_CA_name": "No s'ha pogut analitzar el nom de l'autoritat del certificat auto-signat (fitxer: {file:s})",
"confirm_app_install_warning": "Atenció: aquesta aplicació funciona però no està ben integrada amb YunoHost. Algunes característiques com la autenticació única i la còpia de seguretat/restauració poden no estar disponibles. Voleu instal·lar-la de totes maneres? [{answers:s}] ", "confirm_app_install_warning": "Atenció: Aquesta aplicació funciona, però no està ben integrada amb YunoHost. Algunes característiques com la autenticació única i la còpia de seguretat/restauració poden no estar disponibles. Voleu instal·lar-la de totes maneres? [{answers:s}] ",
"confirm_app_install_danger": "ATENCIÓ! Aquesta aplicació encara és experimental (si no és que no funciona directament) i és probable que trenqui el sistema! No hauríeu d'instal·lar-la a no ser que sapigueu el que feu. Esteu segurs de voler córrer aquest risc? [{answers:s}] ", "confirm_app_install_danger": "PERILL! Aquesta aplicació encara és experimental (si no és que no funciona directament)! No hauríeu d'instal·lar-la a no ser que sapigueu el que feu. No obtindreu CAP AJUDA si l'aplicació no funciona o trenca el sistema… Si accepteu el risc, escriviu «{answers:s}»",
"confirm_app_install_thirdparty": "ATENCIÓ! La instal·lació d'aplicacions de terceres parts pot comprometre la integritat i seguretat del seu sistema. Faci-ho sota la seva responsabilitat.No hauríeu d'instal·lar-ne a no ser que sapigueu el que feu. Esteu segurs de voler córrer aquest risc? [{answers:s}] ", "confirm_app_install_thirdparty": "PERILL! Aquesta aplicació no es part del catàleg d'aplicacions de YunoHost. La instal·lació d'aplicacions de terceres parts pot comprometre la integritat i seguretat del seu sistema. No hauríeu d'instal·lar-ne a no ser que sapigueu el que feu. No obtindreu CAP AJUDA si l'aplicació no funciona o trenca el sistema… Si accepteu el risc, escriviu «{answers:s}»",
"custom_app_url_required": "Heu de especificar una URL per actualitzar la vostra aplicació personalitzada {app:s}", "custom_app_url_required": "Heu de especificar una URL per actualitzar la vostra aplicació personalitzada {app:s}",
"custom_appslist_name_required": "Heu d'especificar un nom per la vostra llista d'aplicacions personalitzada", "custom_appslist_name_required": "Heu d'especificar un nom per la vostra llista d'aplicacions personalitzada",
"diagnosis_debian_version_error": "No s'ha pogut obtenir la versió Debian: {error}", "diagnosis_debian_version_error": "No s'ha pogut obtenir la versió Debian: {error}",
@ -158,24 +158,24 @@
"diagnosis_monitor_disk_error": "No es poden monitorar els discs: {error}", "diagnosis_monitor_disk_error": "No es poden monitorar els discs: {error}",
"diagnosis_monitor_network_error": "No es pot monitorar la xarxa: {error}", "diagnosis_monitor_network_error": "No es pot monitorar la xarxa: {error}",
"diagnosis_monitor_system_error": "No es pot monitorar el sistema: {error}", "diagnosis_monitor_system_error": "No es pot monitorar el sistema: {error}",
"diagnosis_no_apps": "No hi ha cap aplicació instal·lada", "diagnosis_no_apps": "Aquesta aplicació no està instal·lada",
"admin_password_too_long": "Trieu una contrasenya de menys de 127 caràcters", "admin_password_too_long": "Trieu una contrasenya de menys de 127 caràcters",
"dpkg_is_broken": "No es pot fer això en aquest instant perquè dpkg/apt (els gestors de paquets del sistema) sembla estar mal configurat... Podeu intentar solucionar-ho connectant-vos per ssh i executant \"sudo dpkg --configure -a\".", "dpkg_is_broken": "No es pot fer això en aquest instant perquè dpkg/APT (els gestors de paquets del sistema) sembla estar mal configurat… Podeu intentar solucionar-ho connectant-vos per SSH i executant «sudo dpkg --configure -a».",
"dnsmasq_isnt_installed": "sembla que dnsmasq no està instal·lat, executeu \"apt-get remove bind9 && apt-get install dnsmasq\"", "dnsmasq_isnt_installed": "sembla que dnsmasq no està instal·lat, executeu \"apt-get remove bind9 && apt-get install dnsmasq\"",
"domain_cannot_remove_main": "No es pot eliminar el domini principal. S'ha d'establir un nou domini primer", "domain_cannot_remove_main": "No es pot eliminar el domini principal. S'ha d'establir un nou domini primer",
"domain_cert_gen_failed": "No s'ha pogut generar el certificat", "domain_cert_gen_failed": "No s'ha pogut generar el certificat",
"domain_created": "S'ha creat el domini", "domain_created": "S'ha creat el domini",
"domain_creation_failed": "No s'ha pogut crear el domini", "domain_creation_failed": "No s'ha pogut crear el domini {domain}: {error}",
"domain_deleted": "S'ha eliminat el domini", "domain_deleted": "S'ha eliminat el domini",
"domain_deletion_failed": "No s'ha pogut eliminar el domini", "domain_deletion_failed": "No s'ha pogut eliminar el domini {domini}: {error}",
"domain_exists": "El domini ja existeix", "domain_exists": "El domini ja existeix",
"app_action_cannot_be_ran_because_required_services_down": "Aquesta aplicació necessita serveis que estan aturats. Abans de continuar, hauríeu d'intentar arrancar de nou els serveis següents (i també investigar perquè estan aturats) : {services}", "app_action_cannot_be_ran_because_required_services_down": "Aquests serveis necessaris haurien d'estar funcionant per poder executar aquesta acció: {services} Intenteu reiniciar-los per continuar (i possiblement investigar perquè estan aturats).",
"domain_dns_conf_is_just_a_recommendation": "Aquesta ordre mostra la configuració *recomanada*. En cap cas fa la configuració del DNS. És la vostra responsabilitat configurar la zona DNS en el vostre registrar en acord amb aquesta recomanació.", "domain_dns_conf_is_just_a_recommendation": "Aquesta ordre mostra la configuració *recomanada*. En cap cas fa la configuració del DNS. És la vostra responsabilitat configurar la zona DNS en el vostre registrar en acord amb aquesta recomanació.",
"domain_dyndns_already_subscribed": "Ja us heu subscrit a un domini DynDNS", "domain_dyndns_already_subscribed": "Ja us heu subscrit a un domini DynDNS",
"domain_dyndns_dynette_is_unreachable": "No s'ha pogut abastar la dynette YunoHost, o bé YunoHost no està connectat a internet correctament o bé el servidor dynette està caigut. Error: {error}", "domain_dyndns_dynette_is_unreachable": "No s'ha pogut abastar la dynette YunoHost, o bé YunoHost no està connectat a internet correctament o bé el servidor dynette està caigut. Error: {error}",
"domain_dyndns_invalid": "Domini no vàlid per utilitzar amb DynDNS", "domain_dyndns_invalid": "Domini no vàlid per utilitzar amb DynDNS",
"domain_dyndns_root_unknown": "Domini DynDNS principal desconegut", "domain_dyndns_root_unknown": "Domini DynDNS principal desconegut",
"domain_hostname_failed": "No s'ha pogut establir un nou nom d'amfitrió. Això podria causar problemes més tard (no és segur ... podria no passar res).", "domain_hostname_failed": "No s'ha pogut establir un nou nom d'amfitrió. Això podria causar problemes més tard (podria no passar res).",
"domain_uninstall_app_first": "Hi ha una o més aplicacions instal·lades en aquest domini. Desinstal·leu les abans d'eliminar el domini", "domain_uninstall_app_first": "Hi ha una o més aplicacions instal·lades en aquest domini. Desinstal·leu les abans d'eliminar el domini",
"domain_unknown": "Domini desconegut", "domain_unknown": "Domini desconegut",
"domain_zone_exists": "El fitxer de zona DNS ja existeix", "domain_zone_exists": "El fitxer de zona DNS ja existeix",
@ -187,61 +187,61 @@
"dyndns_could_not_check_available": "No s'ha pogut verificar la disponibilitat de {domain:s} a {provider:s}.", "dyndns_could_not_check_available": "No s'ha pogut verificar la disponibilitat de {domain:s} a {provider:s}.",
"dyndns_ip_update_failed": "No s'ha pogut actualitzar l'adreça IP al DynDNS", "dyndns_ip_update_failed": "No s'ha pogut actualitzar l'adreça IP al DynDNS",
"dyndns_ip_updated": "S'ha actualitzat l'adreça IP al DynDNS", "dyndns_ip_updated": "S'ha actualitzat l'adreça IP al DynDNS",
"dyndns_key_generating": "S'està generant la clau DNS, això pot trigar una estona…", "dyndns_key_generating": "S'està generant la clau DNS… això pot trigar una estona.",
"dyndns_key_not_found": "No s'ha trobat la clau DNS pel domini", "dyndns_key_not_found": "No s'ha trobat la clau DNS pel domini",
"dyndns_no_domain_registered": "No hi ha cap domini registrat amb DynDNS", "dyndns_no_domain_registered": "No hi ha cap domini registrat amb DynDNS",
"dyndns_registered": "S'ha registrat el domini DynDNS", "dyndns_registered": "S'ha registrat el domini DynDNS",
"dyndns_registration_failed": "No s'ha pogut registrar el domini DynDNS: {error:s}", "dyndns_registration_failed": "No s'ha pogut registrar el domini DynDNS: {error:s}",
"dyndns_domain_not_provided": "El proveïdor {provider:s} no pot oferir el domini {domain:s}.", "dyndns_domain_not_provided": "El proveïdor de DynDNS {provider:s} no pot oferir el domini {domain:s}.",
"dyndns_unavailable": "El domini {domain:s} no està disponible.", "dyndns_unavailable": "El domini {domain:s} no està disponible.",
"executing_command": "Execució de l'ordre « {command:s} »…", "executing_command": "Execució de l'ordre « {command:s} »…",
"executing_script": "Execució de l'script « {script:s} »…", "executing_script": "Execució de l'script « {script:s} »…",
"extracting": "Extracció en curs…", "extracting": "Extracció en curs…",
"dyndns_cron_installed": "S'ha instal·lat la tasca cron pel DynDNS", "dyndns_cron_installed": "S'ha creat la tasca cron pel DynDNS",
"dyndns_cron_remove_failed": "No s'ha pogut eliminar la tasca cron per a DynDNS: {error}", "dyndns_cron_remove_failed": "No s'ha pogut eliminar la tasca cron per a DynDNS: {error}",
"dyndns_cron_removed": "S'ha eliminat la tasca cron pel DynDNS", "dyndns_cron_removed": "S'ha eliminat la tasca cron pel DynDNS",
"experimental_feature": "Atenció: aquesta funcionalitat és experimental i no es considera estable, no s'ha d'utilitzar a excepció de saber el que esteu fent.", "experimental_feature": "Atenció: Aquesta funcionalitat és experimental i no es considera estable, no s'ha d'utilitzar a excepció de saber el que esteu fent.",
"field_invalid": "Camp incorrecte « {:s} »", "field_invalid": "Camp incorrecte « {:s} »",
"file_does_not_exist": "El camí {path:s} no existeix.", "file_does_not_exist": "El camí {path:s} no existeix.",
"firewall_reload_failed": "No s'ha pogut tornar a carregar el tallafoc", "firewall_reload_failed": "No s'ha pogut tornar a carregar el tallafocs",
"firewall_reloaded": "S'ha tornat a carregar el tallafoc", "firewall_reloaded": "S'ha tornat a carregar el tallafocs",
"firewall_rules_cmd_failed": "No s'han pogut aplicar algunes regles del tallafoc. Mireu el registre per a més informació.", "firewall_rules_cmd_failed": "No s'han pogut aplicar algunes regles del tallafocs. Més informació en el registre.",
"format_datetime_short": "%d/%m/%Y %H:%M", "format_datetime_short": "%d/%m/%Y %H:%M",
"global_settings_bad_choice_for_enum": "Opció pel paràmetre {setting:s} incorrecta, s'ha rebut «{choice:s}» però les opcions disponibles són: {available_choices:s}", "global_settings_bad_choice_for_enum": "Opció pel paràmetre {setting:s} incorrecta, s'ha rebut «{choice:s}», però les opcions disponibles són: {available_choices:s}",
"global_settings_bad_type_for_setting": "El tipus del paràmetre {setting:s} és incorrecte. S'ha rebut {received_type:s}, però s'esperava {expected_type:s}", "global_settings_bad_type_for_setting": "El tipus del paràmetre {setting:s} és incorrecte. S'ha rebut {received_type:s}, però s'esperava {expected_type:s}",
"global_settings_cant_open_settings": "No s'ha pogut obrir el fitxer de configuració, raó: {reason:s}", "global_settings_cant_open_settings": "No s'ha pogut obrir el fitxer de configuració, raó: {reason:s}",
"global_settings_cant_serialize_settings": "No s'ha pogut serialitzar les dades de configuració, raó: {reason:s}", "global_settings_cant_serialize_settings": "No s'ha pogut serialitzar les dades de configuració, raó: {reason:s}",
"global_settings_cant_write_settings": "No s'ha pogut escriure el fitxer de configuració, raó: {reason:s}", "global_settings_cant_write_settings": "No s'ha pogut escriure el fitxer de configuració, raó: {reason:s}",
"global_settings_key_doesnt_exists": "La clau « {settings_key:s} » no existeix en la configuració global, podeu veure totes les claus disponibles executant «yunohost settings list »", "global_settings_key_doesnt_exists": "La clau « {settings_key:s} » no existeix en la configuració global, podeu veure totes les claus disponibles executant «yunohost settings list »",
"global_settings_reset_success": "Èxit. S'ha fet una còpia de seguretat de la configuració anterior a {path:s}", "global_settings_reset_success": "S'ha fet una còpia de seguretat de la configuració anterior a {path:s}",
"global_settings_setting_example_bool": "Exemple d'opció booleana", "global_settings_setting_example_bool": "Exemple d'opció booleana",
"global_settings_setting_example_enum": "Exemple d'opció de tipus enumeració", "global_settings_setting_example_enum": "Exemple d'opció de tipus enumeració",
"global_settings_setting_example_int": "Exemple d'opció de tipus enter", "global_settings_setting_example_int": "Exemple d'opció de tipus enter",
"global_settings_setting_example_string": "Exemple d'opció de tipus cadena", "global_settings_setting_example_string": "Exemple d'opció de tipus cadena",
"global_settings_setting_security_nginx_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor web nginx. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)", "global_settings_setting_security_nginx_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor web NGINX. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)",
"global_settings_setting_security_password_admin_strength": "Robustesa de la contrasenya d'administrador", "global_settings_setting_security_password_admin_strength": "Robustesa de la contrasenya d'administrador",
"global_settings_setting_security_password_user_strength": "Robustesa de la contrasenya de l'usuari", "global_settings_setting_security_password_user_strength": "Robustesa de la contrasenya de l'usuari",
"global_settings_setting_security_ssh_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor SSH. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)", "global_settings_setting_security_ssh_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor SSH. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)",
"global_settings_unknown_setting_from_settings_file": "Clau de configuració desconeguda: «{setting_key:s}», refusant-la i guardant-la a /etc/yunohost/settings-unknown.json", "global_settings_unknown_setting_from_settings_file": "Clau de configuració desconeguda: «{setting_key:s}», refusada i guardada a /etc/yunohost/settings-unknown.json",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Permetre la clau d'hoste DSA (obsolet) per la configuració del servei SSH", "global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Permetre la clau d'hoste DSA (obsolet) per la configuració del servei SSH",
"global_settings_unknown_type": "Situació inesperada, la configuració {setting:s} sembla tenir el tipus {unknown_type:s} però no és un tipus reconegut pel sistema.", "global_settings_unknown_type": "Situació inesperada, la configuració {setting:s} sembla tenir el tipus {unknown_type:s} però no és un tipus reconegut pel sistema.",
"good_practices_about_admin_password": "Esteu a punt de definir una nova contrasenya d'administrador. La contrasenya ha de tenir un mínim de 8 caràcters; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials).", "good_practices_about_admin_password": "Esteu a punt de definir una nova contrasenya d'administrador. La contrasenya ha de tenir un mínim de 8 caràcters; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials).",
"hook_exec_failed": "No s'ha pogut executar l'script: {path:s}", "hook_exec_failed": "No s'ha pogut executar el script: {path:s}",
"hook_exec_not_terminated": "L'execució de l'script « {path:s} » no s'ha acabat correctament", "hook_exec_not_terminated": "El script no s'ha acabat correctament: {path:s}",
"hook_json_return_error": "No s'ha pogut llegir el retorn de l'script {path:s}. Error: {msg:s}. Contingut en brut: {raw_content}", "hook_json_return_error": "No s'ha pogut llegir el retorn del script {path:s}. Error: {msg:s}. Contingut en brut: {raw_content}",
"hook_list_by_invalid": "Propietat per llistar les accions invàlida", "hook_list_by_invalid": "Aquesta propietat no es pot utilitzar per llistar els hooks",
"hook_name_unknown": "Nom de script « {name:s} »desconegut", "hook_name_unknown": "Nom de script « {name:s} »desconegut",
"installation_complete": "Instal·lació completada", "installation_complete": "Instal·lació completada",
"installation_failed": "Ha fallat la instal·lació", "installation_failed": "Ha fallat alguna cosa amb la instal·lació",
"invalid_url_format": "Format d'URL invàlid", "invalid_url_format": "Format d'URL invàlid",
"ip6tables_unavailable": "No podeu modificar les ip6tables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció", "ip6tables_unavailable": "No podeu modificar les ip6tables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció",
"iptables_unavailable": "No podeu modificar les iptables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció", "iptables_unavailable": "No podeu modificar les iptables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció",
"log_corrupted_md_file": "El fitxer de metadades yaml associat amb els registres està malmès: « {md_file} »\nError: {error}", "log_corrupted_md_file": "El fitxer de metadades YAML associat amb els registres està malmès: « {md_file} »\nError: {error}",
"log_category_404": "La categoria de registres « {category} » no existeix", "log_category_404": "La categoria de registres « {category} » no existeix",
"log_link_to_log": "El registre complet d'aquesta operació: «<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>»", "log_link_to_log": "El registre complet d'aquesta operació: «<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>»",
"log_help_to_get_log": "Per veure el registre de l'operació « {desc} », utilitzeu l'ordre «yunohost log display {name} »", "log_help_to_get_log": "Per veure el registre de l'operació « {desc} », utilitzeu l'ordre «yunohost log display {name} »",
"log_link_to_failed_log": "L'operació « {dec} » ha fallat! Per obtenir ajuda, <a href=\"#/tools/logs/{name}\">proveïu el registre complete de l'operació clicant aquí</a>", "log_link_to_failed_log": "No s'ha pogut completar l'operació « {desc} ». Per obtenir ajuda, <a href=\"#/tools/logs/{name}\">proveïu el registre complete de l'operació clicant aquí</a>",
"log_help_to_get_failed_log": "L'operació « {dec} » ha fallat! Per obtenir ajuda, compartiu el registre complete de l'operació utilitzant l'ordre «yunohost log display {name} --share»", "log_help_to_get_failed_log": "No s'ha pogut completar l'operació « {desc} ». Per obtenir ajuda, compartiu el registre complete de l'operació utilitzant l'ordre «yunohost log display {name} --share»",
"log_does_exists": "No hi ha cap registre per l'operació amb el nom«{log} », utilitzeu «yunohost log list» per veure tots els registre d'operació disponibles", "log_does_exists": "No hi ha cap registre per l'operació amb el nom«{log} », utilitzeu «yunohost log list» per veure tots els registre d'operació disponibles",
"log_operation_unit_unclosed_properly": "L'operació no s'ha tancat de forma correcta", "log_operation_unit_unclosed_properly": "L'operació no s'ha tancat de forma correcta",
"log_app_addaccess": "Afegir accés a « {} »", "log_app_addaccess": "Afegir accés a « {} »",
@ -263,7 +263,7 @@
"log_domain_remove": "Elimina el domini « {} » de la configuració del sistema", "log_domain_remove": "Elimina el domini « {} » de la configuració del sistema",
"log_dyndns_subscribe": "Subscriure's a un subdomini YunoHost « {} »", "log_dyndns_subscribe": "Subscriure's a un subdomini YunoHost « {} »",
"log_dyndns_update": "Actualitza la IP associada al subdomini YunoHost « {} »", "log_dyndns_update": "Actualitza la IP associada al subdomini YunoHost « {} »",
"log_letsencrypt_cert_install": "Instal·la el certificat Let's Encrypt al domini « {} »", "log_letsencrypt_cert_install": "Instal·la un certificat Let's Encrypt al domini « {} »",
"log_selfsigned_cert_install": "Instal·la el certificat autosignat al domini « {} »", "log_selfsigned_cert_install": "Instal·la el certificat autosignat al domini « {} »",
"log_letsencrypt_cert_renew": "Renova el certificat Let's Encrypt de « {} »", "log_letsencrypt_cert_renew": "Renova el certificat Let's Encrypt de « {} »",
"log_service_enable": "Activa el servei « {} »", "log_service_enable": "Activa el servei « {} »",
@ -278,81 +278,81 @@
"log_tools_upgrade": "Actualitza els paquets del sistema", "log_tools_upgrade": "Actualitza els paquets del sistema",
"log_tools_shutdown": "Apaga el servidor", "log_tools_shutdown": "Apaga el servidor",
"log_tools_reboot": "Reinicia el servidor", "log_tools_reboot": "Reinicia el servidor",
"already_up_to_date": "No hi ha res a fer! Tot està al dia!", "already_up_to_date": "No hi ha res a fer. Tot està actualitzat.",
"dpkg_lock_not_available": "No es pot utilitzar aquesta comanda en aquest moment ja que sembla que un altre programa està utilitzant el lock de dpkg (el gestor de paquets del sistema)", "dpkg_lock_not_available": "No es pot utilitzar aquesta comanda en aquest moment ja que sembla que un altre programa està utilitzant el lock de dpkg (el gestor de paquets del sistema)",
"global_settings_setting_security_postfix_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor Postfix. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)", "global_settings_setting_security_postfix_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor Postfix. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)",
"ldap_init_failed_to_create_admin": "La inicialització de LDAP no ha pogut crear l'usuari admin", "ldap_init_failed_to_create_admin": "La inicialització de LDAP no ha pogut crear l'usuari admin",
"ldap_initialized": "S'ha iniciat LDAP", "ldap_initialized": "S'ha iniciat LDAP",
"license_undefined": "indefinit", "license_undefined": "indefinit",
"mail_alias_remove_failed": "No s'han pogut eliminar els alias del correu «{mail:s}»", "mail_alias_remove_failed": "No s'han pogut eliminar els àlies del correu «{mail:s}»",
"mail_domain_unknown": "Domini d'adreça de correu «{domain:s}» desconegut", "mail_domain_unknown": "El domini «{domain:s}» de l'adreça de correu no és vàlid. Utilitzeu un domini administrat per aquest servidor.",
"mail_forward_remove_failed": "No s'han pogut eliminar el reenviament de correu «{mail:s}»", "mail_forward_remove_failed": "No s'han pogut eliminar el reenviament de correu «{mail:s}»",
"mailbox_used_space_dovecot_down": "S'ha d'engegar el servei de correu Dovecot per poder obtenir l'espai utilitzat per la bústia de correu", "mailbox_used_space_dovecot_down": "S'ha d'engegar el servei de correu Dovecot, per poder obtenir l'espai utilitzat per la bústia de correu",
"mail_unavailable": "Aquesta adreça de correu esta reservada i ha de ser atribuïda automàticament el primer usuari", "mail_unavailable": "Aquesta adreça de correu està reservada i ha de ser atribuïda automàticament el primer usuari",
"main_domain_change_failed": "No s'ha pogut canviar el domini principal", "main_domain_change_failed": "No s'ha pogut canviar el domini principal",
"main_domain_changed": "S'ha canviat el domini principal", "main_domain_changed": "S'ha canviat el domini principal",
"migrate_tsig_end": "La migració cap a hmac-sha512 s'ha acabat", "migrate_tsig_end": "La migració cap a HMAC-SHA-512 s'ha acabat",
"migrate_tsig_failed": "Ha fallat la migració del domini dyndns {domain} cap a hmac-sha512, anul·lant les modificacions. Error: {error_code} - {error}", "migrate_tsig_failed": "Ha fallat la migració del domini DynDNS «{domain}» cap a HMAC-SHA-512, anul·lant les modificacions. Error: {error_code}, {error}",
"migrate_tsig_start": "L'algoritme de generació de claus no es prou segur per a la signatura TSIG del domini «{domain}», començant la migració cap a un de més segur hmac-sha512", "migrate_tsig_start": "L'algoritme de generació de claus no es prou segur per a la signatura TSIG del domini «{domain}», començant la migració cap a un de més segur HMAC-SHA-512",
"migrate_tsig_wait": "Esperar 3 minuts per a que el servidor dyndns tingui en compte la nova clau…", "migrate_tsig_wait": "Esperant tres minuts per a que el servidor DynDNS tingui en compte la nova clau…",
"migrate_tsig_wait_2": "2 minuts…", "migrate_tsig_wait_2": "2 minuts…",
"migrate_tsig_wait_3": "1 minut…", "migrate_tsig_wait_3": "1 minut…",
"migrate_tsig_wait_4": "30 segons…", "migrate_tsig_wait_4": "30 segons…",
"migrate_tsig_not_needed": "Sembla que no s'utilitza cap domini dyndns, no és necessari fer cap migració!", "migrate_tsig_not_needed": "Sembla que no s'utilitza cap domini DynDNS, no és necessari fer cap migració.",
"migration_description_0001_change_cert_group_to_sslcert": "Canvia els permisos del grup dels certificats de «metronome»a «ssl-cert»", "migration_description_0001_change_cert_group_to_sslcert": "Canvia els permisos del grup dels certificats de «metronome»a «ssl-cert»",
"migration_description_0002_migrate_to_tsig_sha256": "Millora la seguretat de dyndns TSIG utilitzant SHA512 en lloc de MD5", "migration_description_0002_migrate_to_tsig_sha256": "Millora la seguretat de DynDNS TSIG utilitzant SHA-512 en lloc de MD5",
"migration_description_0003_migrate_to_stretch": "Actualització del sistema a Debian Stretch i YunoHost 3.0", "migration_description_0003_migrate_to_stretch": "Actualització del sistema a Debian Stretch i YunoHost 3.0",
"migration_description_0004_php5_to_php7_pools": "Tornar a configurar els pools PHP per utilitzar PHP 7 en lloc de PHP 5", "migration_description_0004_php5_to_php7_pools": "Tornar a configurar els pools PHP per utilitzar PHP 7 en lloc de PHP 5",
"migration_description_0005_postgresql_9p4_to_9p6": "Migració de les bases de dades de postgresql 9.4 a 9.6", "migration_description_0005_postgresql_9p4_to_9p6": "Migració de les bases de dades de PostgreSQL 9.4 a 9.6",
"migration_description_0006_sync_admin_and_root_passwords": "Sincronitzar les contrasenyes admin i root", "migration_description_0006_sync_admin_and_root_passwords": "Sincronitzar les contrasenyes admin i root",
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "La configuració SSH serà gestionada per YunoHost (pas 1, automàtic)", "migration_description_0007_ssh_conf_managed_by_yunohost_step1": "La configuració SSH serà gestionada per YunoHost (pas 1, automàtic)",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "La configuració SSH serà gestionada per YunoHost (pas 2, manual)", "migration_description_0008_ssh_conf_managed_by_yunohost_step2": "La configuració SSH serà gestionada per YunoHost (pas 2, manual)",
"migration_description_0009_decouple_regenconf_from_services": "Desvincula el mecanisme regen-conf dels serveis", "migration_description_0009_decouple_regenconf_from_services": "Desvincula el mecanisme regen-conf dels serveis",
"migration_description_0010_migrate_to_apps_json": "Elimina la appslists (desfasat) i utilitza la nova llista unificada «apps.json» en el seu lloc", "migration_description_0010_migrate_to_apps_json": "Elimina les llistes d'aplicacions obsoletes i utilitza la nova llista unificada «apps.json» en el seu lloc",
"migration_0003_backward_impossible": "La migració Stretch no és reversible.", "migration_0003_backward_impossible": "La migració Stretch no és reversible.",
"migration_0003_start": "Ha començat la migració a Stretch. Els registres estaran disponibles a {logfile}.", "migration_0003_start": "Ha començat la migració a Stretch. Els registres estaran disponibles a {logfile}.",
"migration_0003_patching_sources_list": "Modificant el fitxer sources.lists…", "migration_0003_patching_sources_list": "Modificant el fitxer sources.lists…",
"migration_0003_main_upgrade": "Començant l'actualització principal…", "migration_0003_main_upgrade": "Començant l'actualització principal…",
"migration_0003_fail2ban_upgrade": "Començant l'actualització de fail2ban…", "migration_0003_fail2ban_upgrade": "Començant l'actualització de Fail2Ban…",
"migration_0003_restoring_origin_nginx_conf": "El fitxer /etc/nginx/nginx.conf ha estat editat. La migració el tornarà al seu estat original... El fitxer anterior estarà disponible com a {backup_dest}.", "migration_0003_restoring_origin_nginx_conf": "El fitxer /etc/nginx/nginx.conf ha estat editat. La migració el tornarà al seu estat original... El fitxer anterior estarà disponible com a {backup_dest}.",
"migration_0003_yunohost_upgrade": "Començant l'actualització del paquet yunohost... La migració acabarà, però l'actualització actual es farà just després. Després de completar aquesta operació, pot ser que us hagueu de tornar a connectar a la web d'administració.", "migration_0003_yunohost_upgrade": "Començant l'actualització del paquet YunoHost... La migració acabarà, però l'actualització actual es farà just després. Després de completar aquesta operació, pot ser que us hagueu de tornar a connectar a la web d'administració.",
"migration_0003_not_jessie": "La distribució Debian actual no és Jessie!", "migration_0003_not_jessie": "La distribució Debian actual no és Jessie!",
"migration_0003_system_not_fully_up_to_date": "El vostre sistema no està completament actualitzat. S'ha de fer una actualització normal abans de fer la migració a Stretch.", "migration_0003_system_not_fully_up_to_date": "El vostre sistema no està completament actualitzat. S'ha de fer una actualització normal abans de fer la migració a Stretch.",
"migration_0003_still_on_jessie_after_main_upgrade": "Hi ha hagut un problema durant l'actualització principal: el sistema encara està amb Jessie!? Per investigar el problema, mireu el registres a {log}:s…", "migration_0003_still_on_jessie_after_main_upgrade": "Hi ha hagut un problema durant l'actualització principal: El sistema encara està amb Jessie? Per investigar el problema, mireu el registres a {log}:s…",
"migration_0003_general_warning": "Tingueu en compte que la migració és una operació delicada. Tot i que l'equip de YunoHost a fet els possibles per revisar-la i provar-la, la migració pot provocar errors en parts del sistema o aplicacions.\n\nPer tant, recomanem:\n - Fer una còpia de seguretat de les dades o aplicacions importants. Més informació a https://yunohost.org/backup;\n - Sigueu pacient un cop llençada la migració: en funció de la connexió a internet i el maquinari, pot trigar fins a unes hores per actualitzar-ho tot.\n\nD'altra banda, el port per SMTP, utilitzat per clients de correu externs (com Thunderbird o K9-Mail) ha canviat de 465 (SSL/TLS) a 587 (STARTTLS). L'antic port 465 serà tancat automàticament i el nou port 587 serà obert en el tallafocs. Tots els usuaris *hauran* d'adaptar la configuració dels clients de correu en acord amb aquests canvis!", "migration_0003_general_warning": "Tingueu en compte que la migració és una operació delicada. L'equip de YunoHost a fet els possibles per revisar-la i provar-la, però la migració pot provocar errors en parts del sistema o aplicacions.\n\nPer tant, es recomana:\n - Fer una còpia de seguretat de les dades o aplicacions importants. Més informació a https://yunohost.org/backup;\n - Sigueu pacient un cop llençada la migració: en funció de la connexió a internet i el maquinari, pot trigar fins a unes hores per actualitzar-ho tot.\n\nD'altra banda, el port per SMTP, utilitzat per clients de correu externs (com Thunderbird o K9-Mail) ha canviat de 465 (SSL/TLS) a 587 (STARTTLS). L'antic port (465) serà tancat automàticament, i el nou port (587) serà obert en el tallafocs. Tots els usuaris *hauran* d'adaptar la configuració dels clients de correu en acord amb aquests canvis.",
"migration_0003_problematic_apps_warning": "Tingueu en compte que s'han detectat les aplicacions, possiblement, problemàtiques següents. Sembla que aquestes no s'han instal·lat des d'una applist o que no estan marcades com a «working». Per conseqüent, no podem garantir que segueixin funcionant després de l'actualització: {problematic_apps}", "migration_0003_problematic_apps_warning": "Tingueu en compte que s'han detectat les aplicacions, possiblement, problemàtiques següents. Sembla que aquestes no s'han instal·lat des d'una applist, o que no estan marcades com a «working». Per conseqüent, no podem garantir que segueixin funcionant després de l'actualització: {problematic_apps}",
"migration_0003_modified_files": "Tingueu en compte que s'han detectat els següents fitxers que han estat modificats manualment i podrien sobreescriure's al final de l'actualització: {manually_modified_files}", "migration_0003_modified_files": "Tingueu en compte que s'han detectat els següents fitxers que han estat modificats manualment i podrien sobreescriure's al final de l'actualització: {manually_modified_files}",
"migration_0005_postgresql_94_not_installed": "Postgresql no està instal·lat en el sistema. No hi ha res per fer!", "migration_0005_postgresql_94_not_installed": "PostgreSQL no està instal·lat en el sistema. No hi ha res per fer.",
"migration_0005_postgresql_96_not_installed": "S'ha trobat Postgresql 9.4 instal·lat, però no Postgresql 9.6!? Alguna cosa estranya a passat en el sistema :( …", "migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 està instal·lat, però no PostgreSQL 9.6? Alguna cosa estranya a passat en el sistema :( …",
"migration_0005_not_enough_space": "No hi ha prou espai disponible en {path} per fer la migració en aquest moment :(.", "migration_0005_not_enough_space": "Creu espai disponible en {path} per executar la migració.",
"migration_0006_disclaimer": "YunoHost esperar que les contrasenyes admin i root estiguin sincronitzades. Fent aquesta migració, la contrasenya root serà reemplaçada per la contrasenya admin.", "migration_0006_disclaimer": "YunoHost esperar que les contrasenyes de admin i root estiguin sincronitzades. Aquesta migració canvia la contrasenya root per la contrasenya admin.",
"migration_0007_cancelled": "YunoHost no ha pogut millorar la gestió de la configuració SSH.", "migration_0007_cancelled": "No s'ha pogut millorar la gestió de la configuració SSH.",
"migration_0007_cannot_restart": "No es pot reiniciar SSH després d'haver intentat cancel·lar la migració numero 6.", "migration_0007_cannot_restart": "No es pot reiniciar SSH després d'haver intentat cancel·lar la migració numero 6.",
"migration_0008_general_disclaimer": "Per millorar la seguretat del servidor, es recomana que sigui YunoHost qui gestioni la configuració SSH. La configuració SSH actual és diferent a la configuració recomanada. Si deixeu que YunoHost ho reconfiguri, la manera de connectar-se al servidor mitjançant SSH canviarà de la següent manera:", "migration_0008_general_disclaimer": "Per millorar la seguretat del servidor, es recomana que sigui YunoHost qui gestioni la configuració SSH. La configuració SSH actual és diferent a la configuració recomanada. Si deixeu que YunoHost ho reconfiguri, la manera de connectar-se al servidor mitjançant SSH canviarà de la següent manera:",
"migration_0008_port": " - la connexió es farà utilitzant el port 22 en lloc del port SSH personalitzat actual. Es pot reconfigurar;", "migration_0008_port": "• La connexió es farà utilitzant el port 22 en lloc del port SSH personalitzat actual. Es pot reconfigurar;",
"migration_0008_root": " - no es podrà connectar com a root a través de SSH. S'haurà d'utilitzar l'usuari admin per fer-ho;", "migration_0008_root": "• No es podrà connectar com a root a través de SSH. S'haurà d'utilitzar l'usuari admin per fer-ho;",
"migration_0008_dsa": " - es desactivarà la clau DSA. Per tant, es podria haver d'invalidar un missatge esgarrifós del client SSH, i tornar a verificar l'empremta digital del servidor;", "migration_0008_dsa": "• Es desactivarà la clau DSA. Per tant, es podria haver d'invalidar un missatge esgarrifós del client SSH, i tornar a verificar l'empremta digital del servidor;",
"migration_0008_warning": "Si heu entès els avisos i accepteu que YunoHost sobreescrigui la configuració actual, comenceu la migració. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.", "migration_0008_warning": "Si heu entès els avisos i voleu que YunoHost sobreescrigui la configuració actual, comenceu la migració. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.",
"migration_0008_no_warning": "No s'han detectat riscs importants per sobreescriure la configuració SSH, però no es pot estar del tot segur ;)! Si accepteu que YunoHost sobreescrigui la configuració actual, comenceu la migració. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.", "migration_0008_no_warning": "Hauria de ser segur sobreescriure la configuració SSH, però no es pot estar del tot segur! Executetu la migració per sobreescriure-la. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.",
"migration_0009_not_needed": "Sembla que ja s'ha fet aquesta migració? Ometent.", "migration_0009_not_needed": "Sembla que ja s'ha fet aquesta migració… (?) Ometent.",
"migrations_backward": "Migració cap enrere.", "migrations_backward": "Migració cap enrere.",
"migrations_bad_value_for_target": "Nombre invàlid pel paràmetre target, els nombres de migració disponibles són 0 o {}", "migrations_bad_value_for_target": "Nombre invàlid pel paràmetre target, els nombres de migració disponibles són 0 o {}",
"migrations_cant_reach_migration_file": "No s'ha pogut accedir als fitxers de migració al camí %s", "migrations_cant_reach_migration_file": "No s'ha pogut accedir als fitxers de migració al camí «%s»",
"migrations_current_target": "La migració objectiu és {}", "migrations_current_target": "La migració objectiu és {}",
"migrations_error_failed_to_load_migration": "ERROR: no s'ha pogut carregar la migració {number} {name}", "migrations_error_failed_to_load_migration": "ERROR: no s'ha pogut carregar la migració {number} {name}",
"migrations_forward": "Migració endavant", "migrations_forward": "Migració endavant",
"migrations_list_conflict_pending_done": "No es pot utilitzar --previous i --done al mateix temps.", "migrations_list_conflict_pending_done": "No es pot utilitzar «--previous» i «--done» al mateix temps.",
"migrations_loading_migration": "Carregant la migració {number} {name}…", "migrations_loading_migration": "Carregant la migració {id}…",
"migrations_migration_has_failed": "La migració {number} {name} ha fallat amb l'excepció {exception}, cancel·lant", "migrations_migration_has_failed": "La migració {id} ha fallat, cancel·lant. Error: {exception}",
"migrations_no_migrations_to_run": "No hi ha cap migració a fer", "migrations_no_migrations_to_run": "No hi ha cap migració a fer",
"migrations_show_currently_running_migration": "Fent la migració {number} {name}…", "migrations_show_currently_running_migration": "Fent la migració {number} {name}…",
"migrations_show_last_migration": "L'última migració feta és {}", "migrations_show_last_migration": "L'última migració feta és {}",
"migrations_skip_migration": "Saltant migració {number} {name}…", "migrations_skip_migration": "Saltant migració {id}…",
"migrations_success": "S'ha completat la migració {number} {name} amb èxit!", "migrations_success": "S'ha completat la migració {number} {name} amb èxit!",
"migrations_to_be_ran_manually": "La migració {number} {name} s'ha de fer manualment. Aneu a Eines > Migracions a la interfície admin, o executeu «yunohost tools migrations migrate».", "migrations_to_be_ran_manually": "La migració {id} s'ha de fer manualment. Aneu a Eines → Migracions a la interfície admin, o executeu «yunohost tools migrations migrate».",
"migrations_need_to_accept_disclaimer": "Per fer la migració {number} {name}, heu d'acceptar aquesta clàusula de no responsabilitat:\n---\n{disclaimer}\n---\nSi accepteu fer la migració, torneu a executar l'ordre amb l'opció --accept-disclaimer.", "migrations_need_to_accept_disclaimer": "Per fer la migració {id}, heu d'acceptar aquesta clàusula de no responsabilitat:\n---\n{disclaimer}\n---\nSi accepteu fer la migració, torneu a executar l'ordre amb l'opció «--accept-disclaimer».",
"monitor_disabled": "El monitoratge del servidor ha estat desactivat", "monitor_disabled": "S'ha desactivat el monitoratge del servidor",
"monitor_enabled": "El monitoratge del servidor ha estat activat", "monitor_enabled": "S'ha activat el monitoratge del sistema",
"monitor_glances_con_failed": "No s'ha pogut connectar al servidor Glances", "monitor_glances_con_failed": "No s'ha pogut connectar al servidor Glances",
"monitor_not_enabled": "El monitoratge del servidor no està activat", "monitor_not_enabled": "El monitoratge del servidor no està activat",
"monitor_period_invalid": "Període de temps invàlid", "monitor_period_invalid": "Període de temps invàlid",
@ -384,18 +384,18 @@
"pattern_firstname": "Ha de ser un nom vàlid", "pattern_firstname": "Ha de ser un nom vàlid",
"pattern_lastname": "Ha de ser un cognom vàlid", "pattern_lastname": "Ha de ser un cognom vàlid",
"pattern_listname": "Ha d'estar compost per caràcters alfanumèrics i guió baix exclusivament", "pattern_listname": "Ha d'estar compost per caràcters alfanumèrics i guió baix exclusivament",
"pattern_mailbox_quota": "Ha de ser una mida amb el sufix b/k/M/G/T o 0 per desactivar la quota", "pattern_mailbox_quota": "Ha de ser una mida amb el sufix b/k/M/G/T o 0 per no tenir quota",
"pattern_password": "Ha de tenir un mínim de 3 caràcters", "pattern_password": "Ha de tenir un mínim de 3 caràcters",
"pattern_port": "Ha de ser un número de port vàlid (i.e. 0-65535)", "pattern_port": "Ha de ser un número de port vàlid (i.e. 0-65535)",
"pattern_port_or_range": "Ha de ser un número de port vàlid (i.e. 0-65535) o un interval de ports (ex. 100:200)", "pattern_port_or_range": "Ha de ser un número de port vàlid (i.e. 0-65535) o un interval de ports (ex. 100:200)",
"pattern_positive_number": "Ha de ser un nombre positiu", "pattern_positive_number": "Ha de ser un nombre positiu",
"pattern_username": "Ha d'estar compost per caràcters alfanumèrics en minúscula i guió baix exclusivament", "pattern_username": "Ha d'estar compost per caràcters alfanumèrics en minúscula i guió baix exclusivament",
"pattern_password_app": "Les contrasenyes no haurien de tenir els següents caràcters: {forbidden_chars}", "pattern_password_app": "Les contrasenyes no poden de tenir els següents caràcters: {forbidden_chars}",
"port_already_closed": "El port {port:d} ja està tancat per les connexions {ip_version:s}", "port_already_closed": "El port {port:d} ja està tancat per les connexions {ip_version:s}",
"port_already_opened": "El port {port:d} ja està obert per les connexions {ip_version:s}", "port_already_opened": "El port {port:d} ja està obert per les connexions {ip_version:s}",
"port_available": "El port {port:d} està disponible", "port_available": "El port {port:d} està disponible",
"port_unavailable": "El port {port:d} no està disponible", "port_unavailable": "El port {port:d} no està disponible",
"recommend_to_add_first_user": "La post instal·lació s'ha acabat, però YunoHost necessita com a mínim un usuari per funcionar correctament, hauríeu d'afegir un usuari executant «yunohost user create $username» o amb la interfície d'administració.", "recommend_to_add_first_user": "La post instal·lació s'ha acabat, però YunoHost necessita com a mínim un usuari per funcionar correctament, hauríeu d'afegir un usuari executant «yunohost user create <username>»; o fer-ho des de la interfície d'administració.",
"regenconf_file_backed_up": "S'ha guardat una còpia de seguretat del fitxer de configuració «{conf}» a «{backup}»", "regenconf_file_backed_up": "S'ha guardat una còpia de seguretat del fitxer de configuració «{conf}» a «{backup}»",
"regenconf_file_copy_failed": "No s'ha pogut copiar el nou fitxer de configuració «{new}» a «{conf}»", "regenconf_file_copy_failed": "No s'ha pogut copiar el nou fitxer de configuració «{new}» a «{conf}»",
"regenconf_file_kept_back": "S'espera que el fitxer de configuració «{conf}» sigui suprimit per regen-conf (categoria {category}) però s'ha mantingut.", "regenconf_file_kept_back": "S'espera que el fitxer de configuració «{conf}» sigui suprimit per regen-conf (categoria {category}) però s'ha mantingut.",
@ -406,26 +406,26 @@
"regenconf_file_updated": "El fitxer de configuració «{conf}» ha estat actualitzat", "regenconf_file_updated": "El fitxer de configuració «{conf}» ha estat actualitzat",
"regenconf_now_managed_by_yunohost": "El fitxer de configuració «{conf}» serà gestionat per YunoHost a partir d'ara (categoria {category}).", "regenconf_now_managed_by_yunohost": "El fitxer de configuració «{conf}» serà gestionat per YunoHost a partir d'ara (categoria {category}).",
"regenconf_up_to_date": "La configuració ja està al dia per la categoria «{category}»", "regenconf_up_to_date": "La configuració ja està al dia per la categoria «{category}»",
"regenconf_updated": "La configuració ha estat actualitzada per la categoria «{category}»", "regenconf_updated": "La configuració per la categoria «{category}» ha estat actualitzada",
"regenconf_would_be_updated": "La configuració hagués estat actualitzada per la categoria «{category}»", "regenconf_would_be_updated": "La configuració hagués estat actualitzada per la categoria «{category}»",
"regenconf_dry_pending_applying": "Verificació de la configuració pendent que s'hauria d'haver aplicat per la categoria «{category}»…", "regenconf_dry_pending_applying": "Verificació de la configuració pendent que s'hauria d'haver aplicat per la categoria «{category}»…",
"regenconf_failed": "No s'ha pogut regenerar la configuració per la/les categoria/es : {categories}", "regenconf_failed": "No s'ha pogut regenerar la configuració per la/les categoria/es : {categories}",
"regenconf_pending_applying": "Aplicació de la configuració pendent per la categoria «{category}»…", "regenconf_pending_applying": "Aplicació de la configuració pendent per la categoria «{category}»…",
"restore_action_required": "S'ha d'especificar quelcom a restaurar", "restore_action_required": "S'ha d'especificar quelcom a restaurar",
"restore_already_installed_app": "Ja hi ha una aplicació instal·lada amb l'id «{app:s}»", "restore_already_installed_app": "Una aplicació amb la ID «{app:s}» ja està instal·lada",
"restore_app_failed": "No s'ha pogut restaurar l'aplicació «{app:s}»", "restore_app_failed": "No s'ha pogut restaurar l'aplicació «{app:s}»",
"restore_cleaning_failed": "No s'ha pogut netejar el directori temporal de restauració", "restore_cleaning_failed": "No s'ha pogut netejar el directori temporal de restauració",
"restore_complete": "Restauració completada", "restore_complete": "Restauració completada",
"restore_confirm_yunohost_installed": "Esteu segur de voler restaurar un sistema ja instal·lat? [{answers:s}]", "restore_confirm_yunohost_installed": "Esteu segur de voler restaurar un sistema ja instal·lat? [{answers:s}]",
"restore_extracting": "Extracció dels fitxers necessaris de l'arxiu…", "restore_extracting": "Extracció dels fitxers necessaris de l'arxiu…",
"restore_failed": "No s'ha pogut restaurar el sistema", "restore_failed": "No s'ha pogut restaurar el sistema",
"restore_hook_unavailable": "L'script de restauració «{part:s}» no està disponible en el sistema i tampoc és en l'arxiu", "restore_hook_unavailable": "El script de restauració «{part:s}» no està disponible en el sistema i tampoc és en l'arxiu",
"restore_may_be_not_enough_disk_space": "Sembla que no hi ha prou espai disponible en el disc (espai lliure: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)", "restore_may_be_not_enough_disk_space": "Sembla que no hi ha prou espai disponible en el sistema (lliure: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)",
"restore_mounting_archive": "Muntatge de l'arxiu a «{path:s}»", "restore_mounting_archive": "Muntatge de l'arxiu a «{path:s}»",
"restore_not_enough_disk_space": "No hi ha prou espai disponible en el disc (espai lliure: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)", "restore_not_enough_disk_space": "No hi ha prou espai disponible (espai: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)",
"restore_nothings_done": "No s'ha restaurat res", "restore_nothings_done": "No s'ha restaurat res",
"restore_removing_tmp_dir_failed": "No s'ha pogut eliminar un directori temporal antic", "restore_removing_tmp_dir_failed": "No s'ha pogut eliminar un directori temporal antic",
"restore_running_app_script": "Execució de l'script de restauració de l'aplicació «{app:s}»…", "restore_running_app_script": "Restaurant l'aplicació «{app:s}»…",
"restore_running_hooks": "Execució dels hooks de restauració…", "restore_running_hooks": "Execució dels hooks de restauració…",
"restore_system_part_failed": "No s'ha pogut restaurar la part «{part:s}» del sistema", "restore_system_part_failed": "No s'ha pogut restaurar la part «{part:s}» del sistema",
"root_password_desynchronized": "S'ha canviat la contrasenya d'administració, però YunoHost no ha pogut propagar-ho cap a la contrasenya root!", "root_password_desynchronized": "S'ha canviat la contrasenya d'administració, però YunoHost no ha pogut propagar-ho cap a la contrasenya root!",
@ -436,31 +436,31 @@
"server_reboot_confirm": "Es reiniciarà el servidor immediatament, n'esteu segur? [{answers:s}]", "server_reboot_confirm": "Es reiniciarà el servidor immediatament, n'esteu segur? [{answers:s}]",
"service_add_failed": "No s'ha pogut afegir el servei «{service:s}»", "service_add_failed": "No s'ha pogut afegir el servei «{service:s}»",
"service_added": "S'ha afegit el servei «{service:s}»", "service_added": "S'ha afegit el servei «{service:s}»",
"service_already_started": "Ja s'ha iniciat el servei «{service:s}»", "service_already_started": "El servei «{service:s}» ja està funcionant",
"service_already_stopped": "Ja s'ha aturat el servei «{service:s}»", "service_already_stopped": "Ja s'ha aturat el servei «{service:s}»",
"service_cmd_exec_failed": "No s'ha pogut executar l'ordre «{command:s}»", "service_cmd_exec_failed": "No s'ha pogut executar l'ordre «{command:s}»",
"service_description_avahi-daemon": "permet accedir al servidor via yunohost.local en la xarxa local", "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_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_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", "service_description_fail2ban": "Protegeix contra els atacs de força bruta i a altres atacs provinents d'Internet",
"service_description_glances": "monitora la informació del sistema en el servidor", "service_description_glances": "Monitora la informació del sistema en el servidor",
"service_description_metronome": "gestiona els comptes de missatgeria instantània XMPP", "service_description_metronome": "Gestiona els comptes de missatgeria instantània XMPP",
"service_description_mysql": "guarda les dades de les aplicacions (base de dades SQL)", "service_description_mysql": "Guarda les dades de les aplicacions (base de dades SQL)",
"service_description_nginx": "serveix o permet l'accés a totes les pàgines web allotjades en el servidor", "service_description_nginx": "Serveix o permet l'accés a totes les pàgines web allotjades en el servidor",
"service_description_nslcd": "gestiona les connexions shell dels usuaris YunoHost", "service_description_nslcd": "Gestiona les connexions shell dels usuaris YunoHost",
"service_description_php7.0-fpm": "executa les aplicacions escrites en PHP amb nginx", "service_description_php7.0-fpm": "Executa les aplicacions escrites en PHP amb NGINX",
"service_description_postfix": "utilitzat per enviar i rebre correus", "service_description_postfix": "Utilitzat per enviar i rebre correus",
"service_description_redis-server": "una base de dades especialitzada per l'accés ràpid a dades, files d'espera i comunicació entre programes", "service_description_redis-server": "Una base de dades especialitzada per l'accés ràpid a dades, files d'espera i comunicació entre programes",
"service_description_rmilter": "verifica diferents paràmetres en els correus", "service_description_rmilter": "Verifica diferents paràmetres en els correus",
"service_description_rspamd": "filtra el correu brossa, i altres funcionalitats relacionades al correu", "service_description_rspamd": "Filtra el correu brossa, i altres funcionalitats relacionades amb el correu",
"service_description_slapd": "guarda el usuaris, dominis i informació relacionada", "service_description_slapd": "Guarda el usuaris, dominis i informació relacionada",
"service_description_ssh": "permet la connexió remota al servidor via terminal (protocol SSH)", "service_description_ssh": "Permet la connexió remota al servidor via terminal (protocol SSH)",
"service_description_yunohost-api": "gestiona les interaccions entre la interfície web de YunoHost i el sistema", "service_description_yunohost-api": "Gestiona les interaccions entre la interfície web de YunoHost i el sistema",
"service_description_yunohost-firewall": "gestiona els ports de connexió oberts i tancats als serveis", "service_description_yunohost-firewall": "Gestiona els ports de connexió oberts i tancats als serveis",
"service_disable_failed": "No s'han pogut deshabilitar el servei «{service:s}»\n\nRegistres recents: {logs:s}", "service_disable_failed": "No s'han pogut deshabilitar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_disabled": "S'ha deshabilitat el servei {service:s}", "service_disabled": "S'ha deshabilitat el servei «{service:s}»",
"service_enable_failed": "No s'ha pogut activar el servei «{service:s}»\n\nRegistres recents: {log:s}", "service_enable_failed": "No s'ha pogut activar el servei «{service:s}»\n\nRegistres recents: {log:s}",
"service_enabled": "S'ha activat el servei {service:s}", "service_enabled": "S'ha activat el servei «{service:s}»",
"service_no_log": "No hi ha cap registre pel servei «{service:s}»", "service_no_log": "No hi ha cap registre pel servei «{service:s}»",
"service_regen_conf_is_deprecated": "«yunohost service regen-conf» està desfasat! Utilitzeu «yunohost tools regen-conf» en el seu lloc.", "service_regen_conf_is_deprecated": "«yunohost service regen-conf» està desfasat! Utilitzeu «yunohost tools regen-conf» en el seu lloc.",
"service_remove_failed": "No s'ha pogut eliminar el servei «{service:s}»", "service_remove_failed": "No s'ha pogut eliminar el servei «{service:s}»",
@ -479,26 +479,26 @@
"service_unknown": "Servei «{service:s}» desconegut", "service_unknown": "Servei «{service:s}» desconegut",
"ssowat_conf_generated": "S'ha generat la configuració SSOwat", "ssowat_conf_generated": "S'ha generat la configuració SSOwat",
"ssowat_conf_updated": "S'ha actualitzat la configuració SSOwat", "ssowat_conf_updated": "S'ha actualitzat la configuració SSOwat",
"ssowat_persistent_conf_read_error": "Error en llegir la configuració persistent de SSOwat: {error:s}. Modifiqueu el fitxer /etc/ssowat/conf.json.persistent per arreglar la sintaxi JSON", "ssowat_persistent_conf_read_error": "No s'ha pogut llegir la configuració persistent de SSOwat: {error:s}. Modifiqueu el fitxer /etc/ssowat/conf.json.persistent per arreglar la sintaxi JSON",
"ssowat_persistent_conf_write_error": "Error guardant la configuració persistent de SSOwat: {error:s}. Modifiqueu el fitxer /etc/ssowat/conf.json.persistent per arreglar la sintaxi JSON", "ssowat_persistent_conf_write_error": "No s'ha pogut guardar la configuració persistent de SSOwat: {error:s}. Modifiqueu el fitxer /etc/ssowat/conf.json.persistent per arreglar la sintaxi JSON",
"system_upgraded": "S'ha actualitzat el sistema", "system_upgraded": "S'ha actualitzat el sistema",
"system_username_exists": "El nom d'usuari ja existeix en els usuaris de sistema", "system_username_exists": "El nom d'usuari ja existeix en la llista d'usuaris de sistema",
"this_action_broke_dpkg": "Aquesta acció a trencat dpkg/apt (els gestors de paquets del sistema)… Podeu intentar resoldre el problema connectant-vos amb SSH i executant «sudo dpkg --configure -a».", "this_action_broke_dpkg": "Aquesta acció a trencat dpkg/APT (els gestors de paquets del sistema)… Podeu intentar resoldre el problema connectant-vos amb SSH i executant «sudo dpkg --configure -a».",
"tools_upgrade_at_least_one": "Especifiqueu --apps O --system", "tools_upgrade_at_least_one": "Especifiqueu «--apps», o «--system»",
"tools_upgrade_cant_both": "No es poden actualitzar tant el sistema com les aplicacions al mateix temps", "tools_upgrade_cant_both": "No es poden actualitzar tant el sistema com les aplicacions al mateix temps",
"tools_upgrade_cant_hold_critical_packages": "No es poden mantenir els paquets crítics…", "tools_upgrade_cant_hold_critical_packages": "No es poden mantenir els paquets crítics…",
"tools_upgrade_cant_unhold_critical_packages": "No es poden deixar de mantenir els paquets crítics…", "tools_upgrade_cant_unhold_critical_packages": "No es poden deixar de mantenir els paquets crítics…",
"tools_upgrade_regular_packages": "Actualitzant els paquets «normals» (no relacionats amb YunoHost)…", "tools_upgrade_regular_packages": "Actualitzant els paquets «normals» (no relacionats amb YunoHost)…",
"tools_upgrade_regular_packages_failed": "No s'han pogut actualitzar els paquets següents: {packages_list}", "tools_upgrade_regular_packages_failed": "No s'han pogut actualitzar els paquets següents: {packages_list}",
"tools_upgrade_special_packages": "Actualitzant els paquets «especials» (relacionats amb YunoHost)…", "tools_upgrade_special_packages": "Actualitzant els paquets «especials» (relacionats amb YunoHost)…",
"tools_upgrade_special_packages_explanation": "Aquesta acció s'acabarà, però l'actualització especial continuarà en segon pla. No comenceu cap altra acció al servidor en els pròxims ~10 minuts (depèn de la velocitat del maquinari). Un cop acabat, pot ser que us hagueu de tornar a connectar a la interfície d'administració. Els registres de l'actualització estaran disponibles a Eines > Registres (a la interfície d'administració) o amb «yunohost log list» (a la línia d'ordres).", "tools_upgrade_special_packages_explanation": "Aquesta acció s'acabarà, però l'actualització especial continuarà en segon pla. No comenceu cap altra acció al servidor en els pròxims ~10 minuts (depèn de la velocitat del maquinari). Un cop acabat, pot ser que us hagueu de tornar a connectar a la interfície d'administració. Els registres de l'actualització estaran disponibles a Eines → Registres (a la interfície d'administració) o amb «yunohost log list» (des de la línia d'ordres).",
"tools_upgrade_special_packages_completed": "Actualització dels paquets YunoHost acabada!\nPremeu [Enter] per tornar a la línia d'ordres", "tools_upgrade_special_packages_completed": "Actualització dels paquets YunoHost acabada.\nPremeu [Enter] per tornar a la línia d'ordres",
"unbackup_app": "L'aplicació «{app:s}» no serà guardada", "unbackup_app": "L'aplicació «{app:s}» no serà guardada",
"unexpected_error": "Hi ha hagut un error inesperat: {error}", "unexpected_error": "Hi ha hagut un error inesperat: {error}",
"unit_unknown": "Unitat desconeguda «{unit:s}»", "unit_unknown": "Unitat desconeguda «{unit:s}»",
"unlimit": "Sense quota", "unlimit": "Sense quota",
"unrestore_app": "L'aplicació «{app:s} no serà restaurada", "unrestore_app": "L'aplicació «{app:s} no serà restaurada",
"update_apt_cache_failed": "No s'ha pogut actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}", "update_apt_cache_failed": "No s'ha pogut actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list, que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}",
"update_apt_cache_warning": "Hi ha hagut errors al actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}", "update_apt_cache_warning": "Hi ha hagut errors al actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}",
"updating_apt_cache": "Obtenció de les actualitzacions disponibles per als paquets del sistema…", "updating_apt_cache": "Obtenció de les actualitzacions disponibles per als paquets del sistema…",
"updating_app_lists": "Obtenció de les actualitzacions disponibles per a les aplicacions…", "updating_app_lists": "Obtenció de les actualitzacions disponibles per a les aplicacions…",
@ -507,23 +507,23 @@
"upnp_dev_not_found": "No s'ha trobat cap dispositiu UPnP", "upnp_dev_not_found": "No s'ha trobat cap dispositiu UPnP",
"upnp_disabled": "S'ha desactivat UPnP", "upnp_disabled": "S'ha desactivat UPnP",
"upnp_enabled": "S'ha activat UPnP", "upnp_enabled": "S'ha activat UPnP",
"upnp_port_open_failed": "No s'han pogut obrir els ports UPnP", "upnp_port_open_failed": "No s'ha pogut obrir el port UPnP",
"user_created": "S'ha creat l'usuari", "user_created": "S'ha creat l'usuari",
"user_creation_failed": "No s'ha pogut crear l'usuari", "user_creation_failed": "No s'ha pogut crear l'usuari {user}: {error}",
"user_deleted": "S'ha suprimit l'usuari", "user_deleted": "S'ha suprimit l'usuari",
"user_deletion_failed": "No s'ha pogut suprimir l'usuari", "user_deletion_failed": "No s'ha pogut suprimir l'usuari {user}: {error}",
"user_home_creation_failed": "No s'ha pogut crear la carpeta personal («home») de l'usuari", "user_home_creation_failed": "No s'ha pogut crear la carpeta personal «home» per l'usuari",
"user_info_failed": "No s'ha pogut obtenir la informació de l'usuari", "user_info_failed": "No s'ha pogut obtenir la informació de l'usuari",
"user_unknown": "Usuari desconegut: {user:s}", "user_unknown": "Usuari desconegut: {user:s}",
"user_update_failed": "No s'ha pogut actualitzar l'usuari", "user_update_failed": "No s'ha pogut actualitzar l'usuari {user}: {error}",
"user_updated": "S'ha actualitzat l'usuari", "user_updated": "S'ha canviat la informació de l'usuari",
"users_available": "Usuaris disponibles:", "users_available": "Usuaris disponibles:",
"yunohost_already_installed": "YunoHost ja està instal·lat", "yunohost_already_installed": "YunoHost ja està instal·lat",
"yunohost_ca_creation_failed": "No s'ha pogut crear l'autoritat de certificació", "yunohost_ca_creation_failed": "No s'ha pogut crear l'autoritat de certificació",
"yunohost_ca_creation_success": "S'ha creat l'autoritat de certificació local.", "yunohost_ca_creation_success": "S'ha creat l'autoritat de certificació local.",
"yunohost_configured": "S'ha configurat YunoHost", "yunohost_configured": "YunoHost està configurat",
"yunohost_installing": "Instal·lació de YunoHost…", "yunohost_installing": "Instal·lació de YunoHost…",
"yunohost_not_installed": "YunoHost no està instal·lat o no està instal·lat correctament. Executeu «yunohost tools postinstall»", "yunohost_not_installed": "YunoHost no està instal·lat correctament. Executeu «yunohost tools postinstall»",
"apps_permission_not_found": "No s'ha trobat cap permís per les aplicacions instal·lades", "apps_permission_not_found": "No s'ha trobat cap permís per les aplicacions instal·lades",
"apps_permission_restoration_failed": "Ha fallat el permís «{permission:s}» per la restauració de l'aplicació {app:s}", "apps_permission_restoration_failed": "Ha fallat el permís «{permission:s}» per la restauració de l'aplicació {app:s}",
"backup_permission": "Permís de còpia de seguretat per l'aplicació {app:s}", "backup_permission": "Permís de còpia de seguretat per l'aplicació {app:s}",
@ -534,14 +534,14 @@
"group_already_disallowed": "El grup «{group:s}» ja té els permisos «{permission:s}» desactivats per l'aplicació «{app:s}»", "group_already_disallowed": "El grup «{group:s}» ja té els permisos «{permission:s}» desactivats per l'aplicació «{app:s}»",
"group_name_already_exist": "El grup {name:s} ja existeix", "group_name_already_exist": "El grup {name:s} ja existeix",
"group_created": "S'ha creat el grup «{group}»", "group_created": "S'ha creat el grup «{group}»",
"group_creation_failed": "No s'ha pogut crear el grup «{group}»", "group_creation_failed": "No s'ha pogut crear el grup «{group}»: {error}",
"group_deleted": "S'ha eliminat el grup «{group}»", "group_deleted": "S'ha eliminat el grup «{group}»",
"group_deletion_failed": "No s'ha pogut eliminar el grup «{group}»", "group_deletion_failed": "No s'ha pogut eliminar el grup «{group}»: {error}",
"group_deletion_not_allowed": "El grup {group:s} no es pot eliminar manualment.", "group_deletion_not_allowed": "El grup {group:s} no es pot eliminar manualment.",
"group_info_failed": "Ha fallat la informació del grup", "group_info_failed": "Ha fallat la informació del grup",
"group_unknown": "Grup {group:s} desconegut", "group_unknown": "Grup {group:s} desconegut",
"group_updated": "S'ha actualitzat el grup «{group}»", "group_updated": "S'ha actualitzat el grup «{group}»",
"group_update_failed": "No s'ha pogut actualitzat el grup «{group}»", "group_update_failed": "No s'ha pogut actualitzat el grup «{group}»: {error}",
"log_permission_add": "Afegir el permís «{}» per l'aplicació «{}»", "log_permission_add": "Afegir el permís «{}» per l'aplicació «{}»",
"log_permission_remove": "Suprimir el permís «{}»", "log_permission_remove": "Suprimir el permís «{}»",
"log_permission_update": "Actualitzar el permís «{}» per l'aplicació «{}»", "log_permission_update": "Actualitzar el permís «{}» per l'aplicació «{}»",
@ -550,31 +550,31 @@
"log_user_group_update": "Actualitzar grup «{}»", "log_user_group_update": "Actualitzar grup «{}»",
"log_user_permission_add": "Actualitzar el permís «{}»", "log_user_permission_add": "Actualitzar el permís «{}»",
"log_user_permission_remove": "Actualitzar el permís «{}»", "log_user_permission_remove": "Actualitzar el permís «{}»",
"mailbox_disabled": "La bústia de correu està desactivada per als usuaris {user:s}", "mailbox_disabled": "La bústia de correu està desactivada per al usuari {user:s}",
"migration_description_0011_setup_group_permission": "Configurar el grup d'usuaris i els permisos per les aplicacions i els serveis", "migration_description_0011_setup_group_permission": "Configurar el grup d'usuaris i els permisos per les aplicacions i els serveis",
"migration_0011_backup_before_migration": "Creant una còpia de seguretat de la base de dades LDAP i la configuració de les aplicacions abans d'efectuar la migració.", "migration_0011_backup_before_migration": "Creant una còpia de seguretat de la base de dades LDAP i la configuració de les aplicacions abans d'efectuar la migració.",
"migration_0011_can_not_backup_before_migration": "No s'ha pogut fer la còpia de seguretat abans de la migració. No s'ha pogut fer la migració. Error: {error:s}", "migration_0011_can_not_backup_before_migration": "No s'ha pogut completar la còpia de seguretat abans de que la migració fallés. Error: {error:s}",
"migration_0011_create_group": "Creant un grup per a cada usuari…", "migration_0011_create_group": "Creant un grup per a cada usuari…",
"migration_0011_done": "Migració completa. Ja podeu gestionar grups d'usuaris.", "migration_0011_done": "Migració completada. Ja podeu gestionar grups d'usuaris.",
"migration_0011_LDAP_config_dirty": "Sembla que heu modificat manualment la configuració LDAP. Per fer aquesta migració s'ha d'actualitzar la configuració LDAP.\nGuardeu la configuració actual, reinicieu la configuració original amb l'ordre «yunohost tools regen-conf -f» i torneu a intentar la migració", "migration_0011_LDAP_config_dirty": "Sembla que heu modificat manualment la configuració LDAP. Per fer aquesta migració s'ha d'actualitzar la configuració LDAP.\nGuardeu la configuració actual, reinicieu la configuració original executant l'ordre «yunohost tools regen-conf -f» i torneu a intentar la migració",
"migration_0011_LDAP_update_failed": "Ha fallat l'actualització de LDAP. Error: {error:s}", "migration_0011_LDAP_update_failed": "Ha fallat l'actualització de LDAP. Error: {error:s}",
"migration_0011_migrate_permission": "Fent la migració dels permisos de la configuració de les aplicacions a LDAP…", "migration_0011_migrate_permission": "Fent la migració dels permisos de la configuració de les aplicacions a LDAP…",
"migration_0011_migration_failed_trying_to_rollback": "La migració ha fallat … s'intenta tornar el sistema a l'estat anterior.", "migration_0011_migration_failed_trying_to_rollback": "No s'ha pogut fer la migració… s'intenta tornar el sistema a l'estat anterior.",
"migration_0011_rollback_success": "S'ha tornat el sistema a l'estat anterior.", "migration_0011_rollback_success": "S'ha tornat el sistema a l'estat anterior.",
"migration_0011_update_LDAP_database": "Actualitzant la base de dades LDAP…", "migration_0011_update_LDAP_database": "Actualitzant la base de dades LDAP…",
"migration_0011_update_LDAP_schema": "Actualitzant l'esquema LDAP…", "migration_0011_update_LDAP_schema": "Actualitzant l'esquema LDAP…",
"need_define_permission_before": "Heu de tornar a redefinir els permisos utilitzant «yunohost user permission add -u USER» abans d'eliminar un grup permès", "need_define_permission_before": "Heu de tornar a redefinir els permisos utilitzant «yunohost user permission add -u USER» abans d'eliminar un grup permès",
"permission_already_clear": "Ja s'ha donat el permís «{permission:s}» per l'aplicació {app:s}", "permission_already_clear": "Ja s'ha donat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_already_exist": "El permís «{permission:s}» ja existeix per l'aplicació {app:s}", "permission_already_exist": "El permís «{permission:s}» ja existeix",
"permission_created": "S'ha creat el permís «{permission:s}» per l'aplicació {app:s}", "permission_created": "S'ha creat el permís «{permission:s}»",
"permission_creation_failed": "La creació del permís ha fallat", "permission_creation_failed": "No s'ha pogut crear el permís «{permission}»: {error}",
"permission_deleted": "S'ha eliminat el permís «{permission:s}» per l'aplicació {app:s}", "permission_deleted": "S'ha eliminat el permís «{permission:s}»",
"permission_deletion_failed": "L'eliminació del permís «{permission:s}» per l'aplicació {app:s} ha fallat", "permission_deletion_failed": "No s'ha pogut eliminar el permís «{permission:s}»: {error}",
"permission_not_found": "No s'ha trobat el permís «{permission:s}» per l'aplicació {app:s}", "permission_not_found": "No s'ha trobat el permís «{permission:s}»",
"permission_name_not_valid": "El nom del permís «{permission:s}» no és vàlid", "permission_name_not_valid": "El nom del permís «{permission:s}» no és vàlid",
"permission_update_failed": "L'actualització del permís ha fallat", "permission_update_failed": "No s'ha pogut actualitzar el permís «{permission}»: {error}",
"permission_generated": "S'ha actualitzat la base de dades del permís", "permission_generated": "S'ha actualitzat la base de dades del permís",
"permission_updated": "S'ha actualitzat el permís «{permission:s}» per l'aplicació {app:s}", "permission_updated": "S'ha actualitzat el permís «{permission:s}»",
"permission_update_nothing_to_do": "No hi ha cap permís per actualitzar", "permission_update_nothing_to_do": "No hi ha cap permís per actualitzar",
"remove_main_permission_not_allowed": "No es pot eliminar el permís principal", "remove_main_permission_not_allowed": "No es pot eliminar el permís principal",
"remove_user_of_group_not_allowed": "No es pot eliminar l'usuari {user:s} del grup {group:s}", "remove_user_of_group_not_allowed": "No es pot eliminar l'usuari {user:s} del grup {group:s}",
@ -582,5 +582,49 @@
"tools_update_failed_to_app_fetchlist": "No s'ha pogut actualitzar la llista d'aplicacions de YunoHost a causa de: {error}", "tools_update_failed_to_app_fetchlist": "No s'ha pogut actualitzar la llista d'aplicacions de YunoHost a causa de: {error}",
"user_already_in_group": "L'usuari {user:s} ja és en el grup {group:s}", "user_already_in_group": "L'usuari {user:s} ja és en el grup {group:s}",
"user_not_in_group": "L'usuari {user:s} no és en el grup {group:s}", "user_not_in_group": "L'usuari {user:s} no és en el grup {group:s}",
"migration_description_0012_postgresql_password_to_md5_authentication": "Força l'autenticació postgresql a fer servir md5 per a les connexions locals" "migration_description_0012_postgresql_password_to_md5_authentication": "Força l'autenticació PostgreSQL a fer servir MD5 per a les connexions locals",
"app_full_domain_unavailable": "Aquesta aplicació ha de ser instal·lada en el seu propi domini, però ja hi ha altres aplicacions instal·lades en el domini «{domain}». Podeu utilitzar un subdomini dedicat a aquesta aplicació.",
"migrations_not_pending_cant_skip": "Aquestes migracions no estan pendents, així que no poden ser omeses: {ids}",
"app_action_broke_system": "Aquesta acció sembla haver trencat els següents serveis importants: {services}",
"log_permission_urls": "Actualitzar les URLs relacionades amb el permís «{}»",
"log_user_group_create": "Crear grup «{}»",
"log_user_permission_update": "Actualitzar els accessos per al permís «{}»",
"log_user_permission_reset": "Restablir el permís «{}»",
"permission_already_disallowed": "El grup «{group}» ja té el permís «{permission}» desactivat",
"migrations_already_ran": "Aquestes migracions ja s'han fet: {ids}",
"migrations_dependencies_not_satisfied": "Executeu aquestes migracions: «{dependencies_id}», abans la migració {id}.",
"migrations_failed_to_load_migration": "No s'ha pogut carregar la migració {id}: {error}",
"migrations_exclusive_options": "«--auto», «--skip», i «--force-rerun» són opcions mútuament excloents.",
"migrations_must_provide_explicit_targets": "Heu de proporcionar objectius explícits al utilitzar «--skip» o «--force-rerun»",
"migrations_no_such_migration": "No hi ha cap migració anomenada «{id}»",
"migrations_pending_cant_rerun": "Aquestes migracions encara estan pendents, així que no es poden tornar a executar: {ids}",
"migrations_running_forward": "Executant la migració {id}…",
"migrations_success_forward": "Migració {id} completada",
"apps_already_up_to_date": "Ja estan actualitzades totes les aplicacions",
"dyndns_provider_unreachable": "No s'ha pogut connectar amb el proveïdor Dyndns {provider}: o el vostre YunoHost no està ben connectat a Internet o el servidor dynette està caigut.",
"operation_interrupted": "S'ha interromput manualment l'operació?",
"group_already_exist": "El grup {group} ja existeix",
"group_already_exist_on_system": "El grup {group} ja existeix en els grups del sistema",
"group_cannot_be_edited": "El grup {group} no es pot editar manualment.",
"group_cannot_be_deleted": "El grup {group} no es pot eliminar manualment.",
"group_user_already_in_group": "L'usuari {user} ja està en el grup {group}",
"group_user_not_in_group": "L'usuari {user} no està en el grup {group}",
"log_permission_create": "Crear el permís «{}»",
"log_permission_delete": "Eliminar el permís «{}»",
"migration_0011_failed_to_remove_stale_object": "No s'ha pogut eliminar l'objecte obsolet {dn}: {error}",
"permission_already_allowed": "El grup «{group}» ja té el permís «{permission}» activat",
"permission_cannot_remove_main": "No es permet eliminar un permís principal",
"user_already_exists": "L'usuari «{user}» ja existeix",
"app_upgrade_stopped": "S'ha aturat l'actualització de totes les aplicacions per prevenir possibles danys ja que no s'ha pogut actualitzar una aplicació",
"app_install_failed": "No s'ha pogut instal·lar {app}: {error}",
"app_install_script_failed": "Hi ha hagut un error en el script d'instal·lació de l'aplicació",
"group_cannot_edit_all_users": "El grup «all_users» no es pot editar manualment. És un grup especial destinat a contenir els usuaris registrats a YunoHost",
"group_cannot_edit_visitors": "El grup «visitors» no es pot editar manualment. És un grup especial que representa els visitants anònims",
"group_cannot_edit_primary_group": "El grup «{group}» no es pot editar manualment. És el grup principal destinat a contenir un usuari específic.",
"log_permission_url": "Actualització de la URL associada al permís «{}»",
"migration_0011_slapd_config_will_be_overwritten": "Sembla que heu modificat manualment la configuració de sldap. Per aquesta migració crítica, YunoHost ha de forçar l'actualització de la configuració sldap. Es farà una còpia de seguretat a {conf_backup_folder}.",
"permission_already_up_to_date": "No s'ha actualitzat el permís perquè la petició d'afegir/eliminar ja corresponent a l'estat actual.",
"permission_currently_allowed_for_visitors": "El permís ja el tenen el grup de visitants a més d'altres grups. Segurament s'hauria de revocar el permís al grup dels visitants o eliminar els altres grups als que s'ha atribuït.",
"permission_currently_allowed_for_all_users": "El permís ha el té el grup de tots els usuaris (all_users) a més d'altres grups. Segurament s'hauria de revocar el permís a «all_users» o eliminar els altres grups als que s'ha atribuït.",
"permission_require_account": "El permís {permission} només té sentit per als usuaris que tenen un compte, i per tant no es pot activar per als visitants."
} }

View file

@ -282,7 +282,7 @@
"appslist_name_already_tracked": "Es gibt bereits eine registrierte App-Liste mit Namen {name:s}.", "appslist_name_already_tracked": "Es gibt bereits eine registrierte App-Liste mit Namen {name:s}.",
"appslist_url_already_tracked": "Es gibt bereits eine registrierte Anwendungsliste mit der URL {url:s}.", "appslist_url_already_tracked": "Es gibt bereits eine registrierte Anwendungsliste mit der URL {url:s}.",
"appslist_migrating": "Migriere Anwendungsliste {appslist:s} …", "appslist_migrating": "Migriere Anwendungsliste {appslist:s} …",
"appslist_could_not_migrate": "Konnte Anwendungsliste {appslist:s} nicht migrieren. Konnte die URL nicht verarbeiten... Der alte Cron-Job wurde unter {bkp_file:s} beibehalten.", "appslist_could_not_migrate": "Konnte die Anwendungsliste {appslist:s} nicht migrieren. Konnte die URL nicht verarbeiten... Der alte Cron-Job wurde unter {bkp_file:s} beibehalten.",
"appslist_corrupted_json": "Anwendungslisten konnte nicht geladen werden. Es scheint, dass {filename:s} beschädigt ist.", "appslist_corrupted_json": "Anwendungslisten konnte nicht geladen werden. Es scheint, dass {filename:s} beschädigt ist.",
"yunohost_ca_creation_success": "Die lokale Zertifizierungs-Authorität wurde angelegt.", "yunohost_ca_creation_success": "Die lokale Zertifizierungs-Authorität wurde angelegt.",
"app_already_installed_cant_change_url": "Diese Application ist bereits installiert. Die URL kann durch diese Funktion nicht modifiziert werden. Überprüfe ob `app changeurl` verfügbar ist.", "app_already_installed_cant_change_url": "Diese Application ist bereits installiert. Die URL kann durch diese Funktion nicht modifiziert werden. Überprüfe ob `app changeurl` verfügbar ist.",
@ -413,5 +413,6 @@
"global_settings_setting_security_password_admin_strength": "Stärke des Admin-Passworts", "global_settings_setting_security_password_admin_strength": "Stärke des Admin-Passworts",
"global_settings_key_doesnt_exists": "Der Schlüssel'{settings_key:s}' existiert nicht in den globalen Einstellungen, du kannst alle verfügbaren Schlüssel sehen, indem du 'yunohost settings list' ausführst", "global_settings_key_doesnt_exists": "Der Schlüssel'{settings_key:s}' existiert nicht in den globalen Einstellungen, du kannst alle verfügbaren Schlüssel sehen, indem du 'yunohost settings list' ausführst",
"log_app_makedefault": "Mache '{}' zur Standard-Anwendung", "log_app_makedefault": "Mache '{}' zur Standard-Anwendung",
"hook_json_return_error": "Konnte die Rückkehr vom Einsprungpunkt {path:s} nicht lesen. Fehler: {msg:s}. Unformatierter Inhalt: {raw_content}" "hook_json_return_error": "Konnte die Rückkehr vom Einsprungpunkt {path:s} nicht lesen. Fehler: {msg:s}. Unformatierter Inhalt: {raw_content}",
"app_full_domain_unavailable": "Es tut uns leid, aber diese Anwendung erfordert die Installation einer vollständigen Domäne, aber einige andere Anwendungen sind bereits auf der Domäne'{domain}' installiert. Eine mögliche Lösung ist das Hinzufügen und Verwenden einer Subdomain, die dieser Anwendung zugeordnet ist."
} }

View file

@ -6,7 +6,7 @@
"admin_password_changed": "The administration password got changed", "admin_password_changed": "The administration password got changed",
"admin_password_too_long": "Please choose a password shorter than 127 characters", "admin_password_too_long": "Please choose a password shorter than 127 characters",
"already_up_to_date": "Nothing to do. Everything is already up-to-date.", "already_up_to_date": "Nothing to do. Everything is already up-to-date.",
"app_action_cannot_be_ran_because_required_services_down": "This app requires some services which are currently down. Before continuing, you should try to restart the following services (and possibly investigate why they are down): {services}", "app_action_cannot_be_ran_because_required_services_down": "These required services should be running to run this action: {services}. Try restarting them to continue (and possibly investigate why they are down).",
"app_action_broke_system": "This action seem to have broke these important services: {services}", "app_action_broke_system": "This action seem to have broke these important services: {services}",
"app_already_installed": "{app:s} is already installed", "app_already_installed": "{app:s} is already installed",
"app_already_installed_cant_change_url": "This app is already installed. The URL cannot be changed just by this function. Look into `app changeurl` if it's available.", "app_already_installed_cant_change_url": "This app is already installed. The URL cannot be changed just by this function. Look into `app changeurl` if it's available.",
@ -16,51 +16,55 @@
"app_argument_required": "Argument '{name:s}' is required", "app_argument_required": "Argument '{name:s}' is required",
"app_change_url_failed_nginx_reload": "Could not reload NGINX. Here is the output of 'nginx -t':\n{nginx_errors:s}", "app_change_url_failed_nginx_reload": "Could not reload NGINX. Here is the output of 'nginx -t':\n{nginx_errors:s}",
"app_change_url_identical_domains": "The old and new domain/url_path are identical ('{domain:s}{path:s}'), nothing to do.", "app_change_url_identical_domains": "The old and new domain/url_path are identical ('{domain:s}{path:s}'), nothing to do.",
"app_change_url_no_script": "This application '{app_name:s}' doesn't support URL modification yet. Maybe you should upgrade it.", "app_change_url_no_script": "The app '{app_name:s}' doesn't support URL modification yet. Maybe you should upgrade it.",
"app_change_url_success": "{app:s} URL is now {domain:s}{path:s}", "app_change_url_success": "{app:s} URL is now {domain:s}{path:s}",
"app_extraction_failed": "Could not extract the installation files", "app_extraction_failed": "Could not extract the installation files",
"app_full_domain_unavailable": "Sorry, this app must be installed on a domain of its own, but other apps are already installed on the domain '{domain}'. You could use a subdomain dedicated to this app instead.",
"app_id_invalid": "Invalid app ID", "app_id_invalid": "Invalid app ID",
"app_incompatible": "The app {app} is incompatible with your YunoHost version", "app_incompatible": "The app {app} is incompatible with your YunoHost version",
"app_install_files_invalid": "These files cannot be installed", "app_install_files_invalid": "These files cannot be installed",
"app_install_failed": "Could not install {app}: {error}",
"app_install_script_failed": "An error occurred inside the app installation script",
"app_location_already_used": "The app '{app}' is already installed in ({path})", "app_location_already_used": "The app '{app}' is already installed in ({path})",
"app_make_default_location_already_used": "Can't make the app '{app}' the default on the domain, {domain} is already in use by the other app '{other_app}'", "app_make_default_location_already_used": "Can't make the app '{app}' the default on the domain, '{domain}' is already in use by the other app '{other_app}'",
"app_location_install_failed": "Cannot install the app there because it conflicts with the app '{other_app}' already installed in '{other_path}'", "app_location_install_failed": "Cannot install the app there because it conflicts with the app '{other_app}' already installed in '{other_path}'",
"app_location_unavailable": "This URL is either unavailable, or conflicts with the already installed app(s):\n{apps:s}", "app_location_unavailable": "This URL is either unavailable, or conflicts with the already installed app(s):\n{apps:s}",
"app_manifest_invalid": "Something is wrong with the app manifest: {error}", "app_manifest_invalid": "Something is wrong with the app manifest: {error}",
"app_not_upgraded": "The app '{failed_app}' failed to upgrade, and as a consequence the following apps upgrades have been cancelled: {apps}", "app_not_upgraded": "The app '{failed_app}' failed to upgrade, and as a consequence the following apps upgrades have been cancelled: {apps}",
"app_upgrade_stopped": "The upgrade of all applications has been stopped to prevent possible damage because the previous application failed to upgrade", "app_upgrade_stopped": "Upgrading all apps was stopped to prevent possible damage because one app could not be upgraded",
"app_not_correctly_installed": "{app:s} seems to be incorrectly installed", "app_not_correctly_installed": "{app:s} seems to be incorrectly installed",
"app_not_installed": "Could not find the application '{app:s}' in the list of installed apps: {all_apps}", "app_not_installed": "Could not find the app '{app:s}' in the list of installed apps: {all_apps}",
"app_not_properly_removed": "{app:s} has not been properly removed", "app_not_properly_removed": "{app:s} has not been properly removed",
"app_package_need_update": "The app {app} package needs to be updated to follow YunoHost changes", "app_package_need_update": "The app {app} package needs to be updated to follow YunoHost changes",
"app_removed": "{app:s} removed", "app_removed": "{app:s} removed",
"app_requirements_checking": "Checking required packages for {app}…", "app_requirements_checking": "Checking required packages for {app}…",
"app_requirements_failed": "Some requirements are not met for {app}: {error}", "app_requirements_failed": "Some requirements are not met for {app}: {error}",
"app_requirements_unmeet": "Requirements are not met for {app}, the package {pkgname} ({version}) must be {spec}", "app_requirements_unmeet": "Requirements are not met for {app}, the package {pkgname} ({version}) must be {spec}",
"app_remove_after_failed_install": "Removing the app following the installation failure…",
"app_sources_fetch_failed": "Could not fetch sources files, is the URL correct?", "app_sources_fetch_failed": "Could not fetch sources files, is the URL correct?",
"app_start_install": "Installing application {app}…", "app_start_install": "Installing the app '{app}'…",
"app_start_remove": "Removing application {app}…", "app_start_remove": "Removing the app '{app}'…",
"app_start_backup": "Collecting files to be backed up for {app}…", "app_start_backup": "Collecting files to be backed up for the app '{app}'…",
"app_start_restore": "Restoring application {app}…", "app_start_restore": "Restoring the app '{app}'…",
"app_unknown": "Unknown app", "app_unknown": "Unknown app",
"app_unsupported_remote_type": "Unsupported remote type used for the app", "app_unsupported_remote_type": "Unsupported remote type used for the app",
"app_upgrade_several_apps": "The following apps will be upgraded: {apps}", "app_upgrade_several_apps": "The following apps will be upgraded: {apps}",
"app_upgrade_app_name": "Now upgrading {app}…", "app_upgrade_app_name": "Now upgrading {app}…",
"app_upgrade_failed": "Could not upgrade {app:s}", "app_upgrade_failed": "Could not upgrade {app:s}",
"app_upgrade_some_app_failed": "Some applications could not be upgraded", "app_upgrade_some_app_failed": "Some apps could not be upgraded",
"app_upgraded": "{app:s} upgraded", "app_upgraded": "{app:s} upgraded",
"apps_already_up_to_date": "All applications are already up-to-date", "apps_already_up_to_date": "All apps are already up-to-date",
"apps_permission_not_found": "No permission found for the installed apps", "apps_permission_not_found": "No permission found for the installed apps",
"appslist_corrupted_json": "Could not load the application lists. It looks like {filename:s} is damaged.", "appslist_corrupted_json": "Could not load the app lists. It looks like {filename:s} is damaged.",
"appslist_could_not_migrate": "Could not migrate the app list {appslist:s}! Could not parse the URL… The old cron job was kept kept in {bkp_file:s}.", "appslist_could_not_migrate": "Could not migrate the app list '{appslist:s}'! Could not parse the URL… The old cron job was kept kept in {bkp_file:s}.",
"appslist_fetched": "Updated application list {appslist:s}", "appslist_fetched": "Updated the app list '{appslist:s}'",
"appslist_migrating": "Migrating application list {appslist:s}…", "appslist_migrating": "Migrating the app list '{appslist:s}'…",
"appslist_name_already_tracked": "A registered application list with name {name:s} already exists.", "appslist_name_already_tracked": "A registered app list with the name {name:s} already exists.",
"appslist_removed": "{appslist:s} application list removed", "appslist_removed": "The '{appslist:s}' app list was removed",
"appslist_retrieve_bad_format": "Could not read the fetched application list {appslist:s}", "appslist_retrieve_bad_format": "Could not read the fetched app list '{appslist:s}'",
"appslist_retrieve_error": "Cannot retrieve the remote application list {appslist:s}: {error:s}", "appslist_retrieve_error": "Cannot retrieve the remote app list '{appslist:s}': {error:s}",
"appslist_unknown": "Application list {appslist:s} unknown.", "appslist_unknown": "The app list '{appslist:s}' is unknown.",
"appslist_url_already_tracked": "There is already a registered application list with the URL {url:s}.", "appslist_url_already_tracked": "There is already a registered app list with the URL {url:s}.",
"ask_current_admin_password": "Current administration password", "ask_current_admin_password": "Current administration password",
"ask_email": "E-mail address", "ask_email": "E-mail address",
"ask_firstname": "First name", "ask_firstname": "First name",
@ -86,7 +90,7 @@
"backup_archive_open_failed": "Could not open the backup archive", "backup_archive_open_failed": "Could not open the backup archive",
"backup_archive_system_part_not_available": "System part '{part:s}' unavailable in this backup", "backup_archive_system_part_not_available": "System part '{part:s}' unavailable in this backup",
"backup_archive_writing_error": "Could not add the files '{source:s}' (named in the archive '{dest:s}') to be backed up into the compressed archive '{archive:s}'", "backup_archive_writing_error": "Could not add the files '{source:s}' (named in the archive '{dest:s}') to be backed up into the compressed archive '{archive:s}'",
"backup_ask_for_copying_if_needed": "Some files could not be prepared for backup using the method that avoids temporarily wasting space on the system. To perform the backup, {size:s}MB will be temporarily. Do you agree?", "backup_ask_for_copying_if_needed": "Do you want to perform the backup using {size:s} MB temporarily? (This way is used since some files could not be prepared using a more efficient method.)",
"backup_borg_not_implemented": "The Borg backup method is not yet implemented", "backup_borg_not_implemented": "The Borg backup method is not yet implemented",
"backup_cant_mount_uncompress_archive": "Could not mount the uncompressed archive as write protected", "backup_cant_mount_uncompress_archive": "Could not mount the uncompressed archive as write protected",
"backup_cleaning_failed": "Could not clean-up the temporary backup folder", "backup_cleaning_failed": "Could not clean-up the temporary backup folder",
@ -112,7 +116,7 @@
"backup_output_directory_forbidden": "Pick a different output directory. Backups can not be created in /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var or /home/yunohost.backup/archives sub-folders", "backup_output_directory_forbidden": "Pick a different output directory. Backups can not be created in /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var or /home/yunohost.backup/archives sub-folders",
"backup_output_directory_not_empty": "You should pick an empty output directory", "backup_output_directory_not_empty": "You should pick an empty output directory",
"backup_output_directory_required": "You must provide an output directory for the backup", "backup_output_directory_required": "You must provide an output directory for the backup",
"backup_output_symlink_dir_broken": "You have a broken symlink in place of your archive directory '{path:s}'. You may have a specific setup to backup your data on another filesystem, in this case you probably forgot to remount or plug in your hard-drive or USB key.", "backup_output_symlink_dir_broken": "Your archive directory '{path:s}' is a broken symlink. Maybe you forgot to re/mount or plug in the storage medium it points to.",
"backup_permission": "Backup permission for app {app:s}", "backup_permission": "Backup permission for app {app:s}",
"backup_php5_to_php7_migration_may_fail": "Could not convert your archive to support PHP 7, you may be unable to restore your PHP apps (reason: {error:s})", "backup_php5_to_php7_migration_may_fail": "Could not convert your archive to support PHP 7, you may be unable to restore your PHP apps (reason: {error:s})",
"backup_running_hooks": "Running backup hooks…", "backup_running_hooks": "Running backup hooks…",
@ -142,16 +146,16 @@
"certmanager_no_cert_file": "Could not read the certificate file for the domain {domain:s} (file: {file:s})", "certmanager_no_cert_file": "Could not read the certificate file for the domain {domain:s} (file: {file:s})",
"certmanager_self_ca_conf_file_not_found": "Could not find configuration file for self-signing authority (file: {file:s})", "certmanager_self_ca_conf_file_not_found": "Could not find configuration file for self-signing authority (file: {file:s})",
"certmanager_unable_to_parse_self_CA_name": "Could not parse name of self-signing authority (file: {file:s})", "certmanager_unable_to_parse_self_CA_name": "Could not parse name of self-signing authority (file: {file:s})",
"confirm_app_install_warning": "Warning: This application may work, but is not well-integrated in YunoHost. Some features such as single sign-on and backup/restore might not be available. Install anyway? [{answers:s}] ", "confirm_app_install_warning": "Warning: This app may work, but is not well-integrated in YunoHost. Some features such as single sign-on and backup/restore might not be available. Install anyway? [{answers:s}] ",
"confirm_app_install_danger": "DANGER! This application is known to be still experimental (if not explicitly not working)! You should probably NOT install it unless you know what you are doing. NO SUPPORT will be provided if this app doesn't work or break your system... If you are willing to take that risk anyway, type '{answers:s}'", "confirm_app_install_danger": "DANGER! This app is known to be still experimental (if not explicitly not working)! You should probably NOT install it unless you know what you are doing. NO SUPPORT will be provided if this app doesn't work or break your system If you are willing to take that risk anyway, type '{answers:s}'",
"confirm_app_install_thirdparty": "DANGER! This application is not part of Yunohost's application catalog. Installing third-party applications may compromise the integrity and security of your system. You should probably NOT install it unless you know what you are doing. NO SUPPORT will be provided if this app doesn't work or break your system... If you are willing to take that risk anyway, type '{answers:s}'", "confirm_app_install_thirdparty": "DANGER! This app is not part of Yunohost's app catalog. Installing third-party apps may compromise the integrity and security of your system. You should probably NOT install it unless you know what you are doing. NO SUPPORT will be provided if this app doesn't work or break your system If you are willing to take that risk anyway, type '{answers:s}'",
"custom_app_url_required": "You must provide a URL to upgrade your custom app {app:s}", "custom_app_url_required": "You must provide a URL to upgrade your custom app {app:s}",
"custom_appslist_name_required": "You must provide a name for your custom app list", "custom_appslist_name_required": "You must provide a name for your custom app list",
"diagnosis_debian_version_error": "Could not retrieve the Debian version: {error}", "diagnosis_debian_version_error": "Could not retrieve the Debian version: {error}",
"diagnosis_kernel_version_error": "Could not retrieve kernel version: {error}", "diagnosis_kernel_version_error": "Could not retrieve kernel version: {error}",
"diagnosis_monitor_disk_error": "Could not monitor disks: {error}", "diagnosis_monitor_disk_error": "Could not monitor disks: {error}",
"diagnosis_monitor_system_error": "Could not monitor system: {error}", "diagnosis_monitor_system_error": "Could not monitor system: {error}",
"diagnosis_no_apps": "No installed application", "diagnosis_no_apps": "No such installed app",
"dpkg_is_broken": "You cannot do this right now because dpkg/APT (the system package managers) seems to be in a broken state… You can try to solve this issue by connecting through SSH and running `sudo dpkg --configure -a`.", "dpkg_is_broken": "You cannot do this right now because dpkg/APT (the system package managers) seems to be in a broken state… You can try to solve this issue by connecting through SSH and running `sudo dpkg --configure -a`.",
"dpkg_lock_not_available": "This command can't be ran right now because another program seems to be using the lock of dpkg (the system package manager)", "dpkg_lock_not_available": "This command can't be ran right now because another program seems to be using the lock of dpkg (the system package manager)",
"domain_cannot_remove_main": "You cannot remove '{domain:s}' since it's the main domain, you need first to set another domain as the main domain using 'yunohost domain main-domain -n <another-domain>', here is the list of candidate domains: {other_domains:s}", "domain_cannot_remove_main": "You cannot remove '{domain:s}' since it's the main domain, you need first to set another domain as the main domain using 'yunohost domain main-domain -n <another-domain>', here is the list of candidate domains: {other_domains:s}",
@ -220,6 +224,9 @@
"group_already_exist_on_system": "Group {group} already exists in the system groups", "group_already_exist_on_system": "Group {group} already exists in the system groups",
"group_created": "Group '{group}' created", "group_created": "Group '{group}' created",
"group_creation_failed": "Could not create the group '{group}': {error}", "group_creation_failed": "Could not create the group '{group}': {error}",
"group_cannot_edit_all_users": "The group 'all_users' cannot be edited manually. It is a special group meant to contain all users registered in YunoHost",
"group_cannot_edit_visitors": "The group 'visitors' cannot be edited manually. It is a special group representing anonymous visitors",
"group_cannot_edit_primary_group": "The group '{group}' cannot be edited manually. It is the primary group meant to contain only one specific user.",
"group_cannot_be_edited": "The group {group} cannot be edited manually.", "group_cannot_be_edited": "The group {group} cannot be edited manually.",
"group_cannot_be_deleted": "The group {group} cannot be deleted manually.", "group_cannot_be_deleted": "The group {group} cannot be deleted manually.",
"group_deleted": "Group '{group}' deleted", "group_deleted": "Group '{group}' deleted",
@ -234,7 +241,7 @@
"hook_json_return_error": "Could not read return from hook {path:s}. Error: {msg:s}. Raw content: {raw_content}", "hook_json_return_error": "Could not read return from hook {path:s}. Error: {msg:s}. Raw content: {raw_content}",
"hook_list_by_invalid": "This property can not be used to list hooks", "hook_list_by_invalid": "This property can not be used to list hooks",
"hook_name_unknown": "Unknown hook name '{name:s}'", "hook_name_unknown": "Unknown hook name '{name:s}'",
"installation_complete": "Installation complete", "installation_complete": "Installation completed",
"installation_failed": "Something went wrong with the installation", "installation_failed": "Something went wrong with the installation",
"ip6tables_unavailable": "You cannot play with ip6tables here. You are either in a container or your kernel does not support it", "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", "iptables_unavailable": "You cannot play with iptables here. You are either in a container or your kernel does not support it",
@ -246,13 +253,13 @@
"log_help_to_get_failed_log": "The operation '{desc}' could not be completed. Please share the full log of this operation using the command 'yunohost log display {name} --share' to get help", "log_help_to_get_failed_log": "The operation '{desc}' could not be completed. Please share the full log of this operation using the command 'yunohost log display {name} --share' to get help",
"log_does_exists": "There is not operation log with the name '{log}', use 'yunohost log list' to see all available operation logs", "log_does_exists": "There is not operation log with the name '{log}', use 'yunohost log list' to see all available operation logs",
"log_operation_unit_unclosed_properly": "Operation unit has not been closed properly", "log_operation_unit_unclosed_properly": "Operation unit has not been closed properly",
"log_app_fetchlist": "Add an application list", "log_app_fetchlist": "Add an app list",
"log_app_removelist": "Remove an application list", "log_app_removelist": "Remove an app list",
"log_app_change_url": "Change the URL of '{}' application", "log_app_change_url": "Change the URL of the '{}' app",
"log_app_install": "Install the '{}' application", "log_app_install": "Install the '{}' app",
"log_app_remove": "Remove the '{}' application", "log_app_remove": "Remove the '{}' app",
"log_app_upgrade": "Upgrade the '{}' application", "log_app_upgrade": "Upgrade the '{}' app",
"log_app_makedefault": "Make '{}' the default application", "log_app_makedefault": "Make '{}' the default app",
"log_available_on_yunopaste": "This log is now available via {url}", "log_available_on_yunopaste": "This log is now available via {url}",
"log_backup_restore_system": "Restore system from a backup archive", "log_backup_restore_system": "Restore system from a backup archive",
"log_backup_restore_app": "Restore '{}' from a backup archive", "log_backup_restore_app": "Restore '{}' from a backup archive",
@ -262,12 +269,12 @@
"log_domain_remove": "Remove '{}' domain from system configuration", "log_domain_remove": "Remove '{}' domain from system configuration",
"log_dyndns_subscribe": "Subscribe to a YunoHost subdomain '{}'", "log_dyndns_subscribe": "Subscribe to a YunoHost subdomain '{}'",
"log_dyndns_update": "Update the IP associated with your YunoHost subdomain '{}'", "log_dyndns_update": "Update the IP associated with your YunoHost subdomain '{}'",
"log_letsencrypt_cert_install": "Install a Let's encrypt certificate on '{}' domain", "log_letsencrypt_cert_install": "Install a Let's Encrypt certificate on '{}' domain",
"log_permission_create": "Create permission '{}'", "log_permission_create": "Create permission '{}'",
"log_permission_delete": "Delete permission '{}'", "log_permission_delete": "Delete permission '{}'",
"log_permission_urls": "Update urls related to permission '{}'", "log_permission_url": "Update url related to permission '{}'",
"log_selfsigned_cert_install": "Install self signed certificate on '{}' domain", "log_selfsigned_cert_install": "Install self signed certificate on '{}' domain",
"log_letsencrypt_cert_renew": "Renew '{}' Let's encrypt certificate", "log_letsencrypt_cert_renew": "Renew '{}' Let's Encrypt certificate",
"log_regen_conf": "Regenerate system configurations '{}'", "log_regen_conf": "Regenerate system configurations '{}'",
"log_user_create": "Add '{}' user", "log_user_create": "Add '{}' user",
"log_user_delete": "Delete '{}' user", "log_user_delete": "Delete '{}' user",
@ -287,7 +294,7 @@
"ldap_initialized": "LDAP initialized", "ldap_initialized": "LDAP initialized",
"license_undefined": "undefined", "license_undefined": "undefined",
"mail_alias_remove_failed": "Could not remove e-mail alias '{mail:s}'", "mail_alias_remove_failed": "Could not remove e-mail alias '{mail:s}'",
"mail_domain_unknown": "Unknown e-mail address for domain '{domain:s}'", "mail_domain_unknown": "Invalid e-mail address for domain '{domain:s}'. Please, use a domain administrated by this server.",
"mail_forward_remove_failed": "Could not remove e-mail forwarding '{mail:s}'", "mail_forward_remove_failed": "Could not remove e-mail forwarding '{mail:s}'",
"mailbox_disabled": "E-mail turned off for user {user:s}", "mailbox_disabled": "E-mail turned off for user {user:s}",
"mailbox_used_space_dovecot_down": "The Dovecot mailbox service needs to be up, if you want to fetch used mailbox space", "mailbox_used_space_dovecot_down": "The Dovecot mailbox service needs to be up, if you want to fetch used mailbox space",
@ -329,31 +336,31 @@
"migration_0005_postgresql_94_not_installed": "PostgreSQL was not installed on your system. Nothing to do.", "migration_0005_postgresql_94_not_installed": "PostgreSQL was not installed on your system. Nothing to do.",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 is installed, but not postgresql 9.6‽ Something weird might have happened on your system:(…", "migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 is installed, but not postgresql 9.6‽ Something weird might have happened on your system:(…",
"migration_0005_not_enough_space": "Make sufficient space available in {path} to run the migration.", "migration_0005_not_enough_space": "Make sufficient space available in {path} to run the migration.",
"migration_0006_disclaimer": "YunoHost now expects admin and root passwords to be synchronized. By running this migration, your root password is going to be replaced by the admin password.", "migration_0006_disclaimer": "YunoHost now expects the admin and root passwords to be synchronized. This migration replaces your root password with the admin password.",
"migration_0007_cancelled": "YunoHost has failed to improve the way your SSH conf is managed.", "migration_0007_cancelled": "Could not improve the way your SSH configuration is managed.",
"migration_0007_cannot_restart": "SSH can't be restarted after trying to cancel migration number 6.", "migration_0007_cannot_restart": "SSH can't be restarted after trying to cancel migration number 6.",
"migration_0008_general_disclaimer": "To improve the security of your server, it is recommended to let YunoHost manage the SSH configuration. Your current SSH setup differs from the recommendation. If you let YunoHost reconfigure it, the way you connect to your server through SSH will change thusly:", "migration_0008_general_disclaimer": "To improve the security of your server, it is recommended to let YunoHost manage the SSH configuration. Your current SSH setup differs from the recommendation. If you let YunoHost reconfigure it, the way you connect to your server through SSH will change thusly:",
"migration_0008_port": "• You will have to connect using port 22 instead of your current custom SSH port. Feel free to reconfigure it;", "migration_0008_port": "• You will have to connect using port 22 instead of your current custom SSH port. Feel free to reconfigure it;",
"migration_0008_root": "• You will not be able to connect as root through SSH. Instead you should use the admin user;", "migration_0008_root": "• You will not be able to connect as root through SSH. Instead you should use the admin user;",
"migration_0008_dsa": "• The DSA key will be turned off. Hence, you might need to invalidate a spooky warning from your SSH client, and recheck the fingerprint of your server;", "migration_0008_dsa": "• The DSA key will be turned off. Hence, you might need to invalidate a spooky warning from your SSH client, and recheck the fingerprint of your server;",
"migration_0008_warning": "If you understand those warnings and agree to let YunoHost override your current configuration, run the migration. Otherwise, you can also skip the migration - though it is not recommended.", "migration_0008_warning": "If you understand those warnings and want YunoHost to override your current configuration, run the migration. Otherwise, you can also skip the migration, though it is not recommended.",
"migration_0008_no_warning": "No major risk indentified concerning overriding your SSH configuration—one can however not be absolutely sure ;)! Run the migration to override it. Otherwise, you can also skip the migration - though it is not recommended.", "migration_0008_no_warning": "Overriding your SSH configuration should be safe, though this can not be promised! Run the migration to override it. Otherwise, you can also skip the migration, though it is not recommended.",
"migration_0009_not_needed": "This migration already happened somehow… (?) Skipping.", "migration_0009_not_needed": "This migration already happened somehow… (?) Skipping.",
"migration_0011_backup_before_migration": "Creating a backup of LDAP database and apps settings prior to the actual migration.", "migration_0011_backup_before_migration": "Creating a backup of LDAP database and apps settings prior to the actual migration.",
"migration_0011_can_not_backup_before_migration": "The backup of the system before the migration failed. Migration failed. Error: {error:s}", "migration_0011_can_not_backup_before_migration": "The backup of the system could not be completed before the migration failed. Error: {error:s}",
"migration_0011_create_group": "Creating a group for each user…", "migration_0011_create_group": "Creating a group for each user…",
"migration_0011_done": "Migration successful. You are now able to manage usergroups.", "migration_0011_done": "Migration completed. You are now able to manage usergroups.",
"migration_0011_LDAP_config_dirty": "It look like that you customized your LDAP configuration. For this migration the LDAP configuration needs to be updated.\nYou need to save your current configuration, reintialize the original configuration by running 'yunohost tools regen-conf -f' and retry the migration", "migration_0011_slapd_config_will_be_overwritten": "It looks like you manually edited the slapd configuration. For this critical migration, YunoHost needs to force the update of the slapd configuration. The original files will be backuped in {conf_backup_folder}.",
"migration_0011_LDAP_update_failed": "Could not update LDAP. Error: {error:s}", "migration_0011_LDAP_update_failed": "Could not update LDAP. Error: {error:s}",
"migration_0011_migrate_permission": "Migrating permissions from apps settings to LDAP…", "migration_0011_migrate_permission": "Migrating permissions from apps settings to LDAP…",
"migration_0011_migration_failed_trying_to_rollback": "Migration failed… trying to roll back the system.", "migration_0011_migration_failed_trying_to_rollback": "Could not migrate… trying to roll back the system.",
"migration_0011_rollback_success": "System rolled back.", "migration_0011_rollback_success": "System rolled back.",
"migration_0011_update_LDAP_database": "Updating LDAP database…", "migration_0011_update_LDAP_database": "Updating LDAP database…",
"migration_0011_update_LDAP_schema": "Updating LDAP schema…", "migration_0011_update_LDAP_schema": "Updating LDAP schema…",
"migration_0011_failed_to_remove_stale_object": "Failed to remove stale object {dn}: {error}", "migration_0011_failed_to_remove_stale_object": "Could not remove stale object {dn}: {error}",
"migrations_already_ran": "Those migrations are already done: {ids}", "migrations_already_ran": "Those migrations are already done: {ids}",
"migrations_cant_reach_migration_file": "Could not access migrations files at path %s", "migrations_cant_reach_migration_file": "Could not access migrations files at the path '%s'",
"migrations_dependencies_not_satisfied": "Cannot run migration {id} because first you need to run these migrations: {dependencies_id}", "migrations_dependencies_not_satisfied": "Run these migrations: '{dependencies_id}', before migration {id}.",
"migrations_failed_to_load_migration": "Could not load migration {id}: {error}", "migrations_failed_to_load_migration": "Could not load migration {id}: {error}",
"migrations_exclusive_options": "'--auto', '--skip', and '--force-rerun' are mutually exclusive options.", "migrations_exclusive_options": "'--auto', '--skip', and '--force-rerun' are mutually exclusive options.",
"migrations_list_conflict_pending_done": "You cannot use both '--previous' and '--done' at the same time.", "migrations_list_conflict_pending_done": "You cannot use both '--previous' and '--done' at the same time.",
@ -362,32 +369,32 @@
"migrations_must_provide_explicit_targets": "You must provide explicit targets when using '--skip' or '--force-rerun'", "migrations_must_provide_explicit_targets": "You must provide explicit targets when using '--skip' or '--force-rerun'",
"migrations_need_to_accept_disclaimer": "To run the migration {id}, your must accept the following disclaimer:\n---\n{disclaimer}\n---\nIf you accept to run the migration, please re-run the command with the option '--accept-disclaimer'.", "migrations_need_to_accept_disclaimer": "To run the migration {id}, your must accept the following disclaimer:\n---\n{disclaimer}\n---\nIf you accept to run the migration, please re-run the command with the option '--accept-disclaimer'.",
"migrations_no_migrations_to_run": "No migrations to run", "migrations_no_migrations_to_run": "No migrations to run",
"migrations_no_such_migration": "There is no migration called {id}", "migrations_no_such_migration": "There is no migration called '{id}'",
"migrations_not_pending_cant_skip": "Those migrations are not pending, so cannot be skipped: {ids}", "migrations_not_pending_cant_skip": "Those migrations are not pending, so cannot be skipped: {ids}",
"migrations_pending_cant_rerun": "Those migrations are still pending, so cannot be run again: {ids}", "migrations_pending_cant_rerun": "Those migrations are still pending, so cannot be run again: {ids}",
"migrations_running_forward": "Running migration {id}…", "migrations_running_forward": "Running migration {id}…",
"migrations_skip_migration": "Skipping migration {id}…", "migrations_skip_migration": "Skipping migration {id}…",
"migrations_success_forward": "Migration {id} completed", "migrations_success_forward": "Migration {id} completed",
"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 migrate`.", "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 migrate`.",
"monitor_disabled": "Server monitoring now turned off", "monitor_disabled": "Server monitoring now off",
"monitor_enabled": "Server monitoring now turned on", "monitor_enabled": "Server monitoring now on",
"monitor_glances_con_failed": "Could not connect to Glances server", "monitor_glances_con_failed": "Could not connect to Glances server",
"monitor_not_enabled": "Server monitoring is off", "monitor_not_enabled": "Server monitoring is off",
"monitor_period_invalid": "Invalid time period", "monitor_period_invalid": "Invalid time period",
"monitor_stats_file_not_found": "Statistics file not found", "monitor_stats_file_not_found": "Could not find the statistics file",
"monitor_stats_no_update": "No monitoring statistics to update", "monitor_stats_no_update": "No monitoring statistics to update",
"monitor_stats_period_unavailable": "No available statistics for the period", "monitor_stats_period_unavailable": "No available statistics for the period",
"mountpoint_unknown": "Unknown mountpoint", "mountpoint_unknown": "Unknown mountpoint",
"mysql_db_creation_failed": "MySQL database creation failed", "mysql_db_creation_failed": "Could not create MySQL database",
"mysql_db_init_failed": "MySQL database init failed", "mysql_db_init_failed": "Could not initialize MySQL database",
"mysql_db_initialized": "The MySQL database now initialized", "mysql_db_initialized": "The MySQL database is now initialized",
"network_check_mx_ko": "DNS MX record is not set", "network_check_mx_ko": "DNS MX record is not set",
"network_check_smtp_ko": "Outbound e-mail (SMTP port 25) seems to be blocked by your network", "network_check_smtp_ko": "Outbound e-mail (SMTP port 25) seems to be blocked by your network",
"network_check_smtp_ok": "Outbound e-mail (SMTP port 25) is not blocked", "network_check_smtp_ok": "Outbound e-mail (SMTP port 25) is not blocked",
"no_internet_connection": "Server not connected to the Internet", "no_internet_connection": "The server is not connected to the Internet",
"not_enough_disk_space": "Not enough free space on '{path:s}'", "not_enough_disk_space": "Not enough free space on '{path:s}'",
"operation_interrupted": "The operation was manually interrupted?", "operation_interrupted": "Was the operation manually interrupted?",
"package_not_installed": "Package '{pkgname}' is not installed", "package_not_installed": "The package '{pkgname}' is not installed",
"package_unexpected_error": "An unexpected error occurred processing the package '{pkgname}'", "package_unexpected_error": "An unexpected error occurred processing the package '{pkgname}'",
"package_unknown": "Unknown package '{pkgname}'", "package_unknown": "Unknown package '{pkgname}'",
"packages_upgrade_failed": "Could not upgrade all the packages", "packages_upgrade_failed": "Could not upgrade all the packages",
@ -398,7 +405,7 @@
"password_too_simple_4": "The password needs to be at least 12 characters long and contain a digit, upper, lower and special characters", "password_too_simple_4": "The password needs to be at least 12 characters long and contain a digit, upper, lower and special characters",
"pattern_backup_archive_name": "Must be a valid filename with max 30 characters, alphanumeric and -_. characters only", "pattern_backup_archive_name": "Must be a valid filename with max 30 characters, alphanumeric and -_. characters only",
"pattern_domain": "Must be a valid domain name (e.g. my-domain.org)", "pattern_domain": "Must be a valid domain name (e.g. my-domain.org)",
"pattern_email": "Must be a valid email address (e.g. someone@domain.org)", "pattern_email": "Must be a valid e-mail address (e.g. someone@example.com)",
"pattern_firstname": "Must be a valid first name", "pattern_firstname": "Must be a valid first name",
"pattern_lastname": "Must be a valid last name", "pattern_lastname": "Must be a valid last name",
"pattern_listname": "Must be alphanumeric and underscore characters only", "pattern_listname": "Must be alphanumeric and underscore characters only",
@ -409,18 +416,22 @@
"pattern_positive_number": "Must be a positive number", "pattern_positive_number": "Must be a positive number",
"pattern_username": "Must be lower-case alphanumeric and underscore characters only", "pattern_username": "Must be lower-case alphanumeric and underscore characters only",
"pattern_password_app": "Sorry, passwords can not contain the following characters: {forbidden_chars}", "pattern_password_app": "Sorry, passwords can not contain the following characters: {forbidden_chars}",
"permission_already_allowed": "Group '{group}' already has permission '{permission}' enabled'", "permission_already_allowed": "Group '{group}' already has permission '{permission}' enabled",
"permission_already_disallowed": "Group '{group}' already has permission '{permission}' disabled'", "permission_already_disallowed": "Group '{group}' already has permission '{permission}' disabled'",
"permission_already_exist": "Permission '{permission}' already exists", "permission_already_exist": "Permission '{permission}' already exists",
"permission_already_up_to_date": "The permission was not updated because the addition/removal requests already match the current state.",
"permission_cannot_remove_main": "Removing a main permission is not allowed", "permission_cannot_remove_main": "Removing a main permission is not allowed",
"permission_created": "Permission '{permission:s}' created", "permission_created": "Permission '{permission:s}' created",
"permission_creation_failed": "Could not create permission '{permission}': {error}", "permission_creation_failed": "Could not create permission '{permission}': {error}",
"permission_currently_allowed_for_visitors": "This permission is currently granted to visitors in addition to other groups. You probably want to either remove the 'visitors' permission or remove the other groups it is currently granted to.",
"permission_currently_allowed_for_all_users": "This permission is currently granted to all users in addition to other groups. You probably want to either remove the 'all_users' permission or remove the other groups it is currently granted to.",
"permission_deleted": "Permission '{permission:s}' deleted", "permission_deleted": "Permission '{permission:s}' deleted",
"permission_deletion_failed": "Could not delete permission '{permission}': {error}", "permission_deletion_failed": "Could not delete permission '{permission}': {error}",
"permission_not_found": "Permission '{permission:s}' not found", "permission_not_found": "Permission '{permission:s}' not found",
"permission_update_failed": "Could not update permission '{permission}' : {error}", "permission_update_failed": "Could not update permission '{permission}' : {error}",
"permission_updated": "Permission '{permission:s}' updated", "permission_updated": "Permission '{permission:s}' updated",
"permission_update_nothing_to_do": "No permissions to update", "permission_update_nothing_to_do": "No permissions to update",
"permission_require_account": "Permission {permission} only makes sense for users having an account, and therefore cannot be enabled for visitors.",
"port_already_closed": "Port {port:d} is already closed for {ip_version:s} connections", "port_already_closed": "Port {port:d} is already closed for {ip_version:s} connections",
"port_already_opened": "Port {port:d} is already opened for {ip_version:s} connections", "port_already_opened": "Port {port:d} is already opened for {ip_version:s} connections",
"port_available": "Port {port:d} is available", "port_available": "Port {port:d} is available",
@ -464,7 +475,7 @@
"server_reboot_confirm": "The server will reboot immediatly, are you sure? [{answers:s}]", "server_reboot_confirm": "The server will reboot immediatly, are you sure? [{answers:s}]",
"service_add_failed": "Could not add the service '{service:s}'", "service_add_failed": "Could not add the service '{service:s}'",
"service_added": "The service '{service:s}' added", "service_added": "The service '{service:s}' added",
"service_already_started": "The service '{service:s}' has already been started", "service_already_started": "The service '{service:s}' is running already",
"service_already_stopped": "The service '{service:s}' has already been stopped", "service_already_stopped": "The service '{service:s}' has already been stopped",
"service_cmd_exec_failed": "Could not execute the command '{command:s}'", "service_cmd_exec_failed": "Could not execute the command '{command:s}'",
"service_description_avahi-daemon": "Allows you to reach your server using 'yunohost.local' in your local network", "service_description_avahi-daemon": "Allows you to reach your server using 'yunohost.local' in your local network",
@ -473,10 +484,10 @@
"service_description_fail2ban": "Protects against brute-force and other kinds of attacks from the Internet", "service_description_fail2ban": "Protects against brute-force and other kinds of attacks from the Internet",
"service_description_glances": "Monitors system info on your server", "service_description_glances": "Monitors system info on your server",
"service_description_metronome": "Manage XMPP instant messaging accounts", "service_description_metronome": "Manage XMPP instant messaging accounts",
"service_description_mysql": "Stores applications data (SQL database)", "service_description_mysql": "Stores app data (SQL database)",
"service_description_nginx": "Serves or provides access to all the websites hosted on your server", "service_description_nginx": "Serves or provides access to all the websites hosted on your server",
"service_description_nslcd": "Handles YunoHost user shell connection", "service_description_nslcd": "Handles YunoHost user shell connection",
"service_description_php7.0-fpm": "Runs applications written in PHP with NGINX", "service_description_php7.0-fpm": "Runs apps written in PHP with NGINX",
"service_description_postfix": "Used to send and receive e-mails", "service_description_postfix": "Used to send and receive e-mails",
"service_description_redis-server": "A specialized database used for rapid data access, task queue, and communication between programs", "service_description_redis-server": "A specialized database used for rapid data access, task queue, and communication between programs",
"service_description_rmilter": "Checks various parameters in e-mails", "service_description_rmilter": "Checks various parameters in e-mails",
@ -484,30 +495,28 @@
"service_description_slapd": "Stores users, domains and related info", "service_description_slapd": "Stores users, domains and related info",
"service_description_ssh": "Allows you to connect remotely to your server via a terminal (SSH protocol)", "service_description_ssh": "Allows you to connect remotely to your server via a terminal (SSH protocol)",
"service_description_yunohost-api": "Manages interactions between the YunoHost web interface and the system", "service_description_yunohost-api": "Manages interactions between the YunoHost web interface and the system",
"service_description_yunohost-firewall": "Manages open and close connexion ports to services", "service_description_yunohost-firewall": "Manages open and close connection ports to services",
"service_disable_failed": "Could not turn off the service '{service:s}'\n\nRecent service logs:{logs:s}", "service_disable_failed": "Could not turn off the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_disabled": "'{service:s}' service turned off", "service_disabled": "The '{service:s}' service was turned off",
"service_enable_failed": "Could not turn on the service '{service:s}'\n\nRecent service logs:{logs:s}", "service_enable_failed": "Could not turn on the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_enabled": "'{service:s}' service turned off", "service_enabled": "The '{service:s}' service was turned off",
"service_no_log": "No log to display for service '{service:s}'", "service_no_log": "No logs to display for the service '{service:s}'",
"service_regen_conf_is_deprecated": "'yunohost service regen-conf' is deprecated! Please use 'yunohost tools regen-conf' instead.", "service_regen_conf_is_deprecated": "'yunohost service regen-conf' is deprecated! Please use 'yunohost tools regen-conf' instead.",
"service_remove_failed": "Could not remove the service '{service:s}'", "service_remove_failed": "Could not remove the service '{service:s}'",
"service_removed": "'{service:s}' service removed", "service_removed": "'{service:s}' service removed",
"service_reload_failed": "Could not reload the service '{service:s}'\n\nRecent service logs:{logs:s}", "service_reload_failed": "Could not reload the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_reloaded": "'{service:s}' service reloaded", "service_reloaded": "The '{service:s}' service was reloaded",
"service_restart_failed": "Could not restart the service '{service:s}'\n\nRecent service logs:{logs:s}", "service_restart_failed": "Could not restart the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_restarted": "'{service:s}' service restarted", "service_restarted": "'{service:s}' service restarted",
"service_reload_or_restart_failed": "Could not reload or restart the service '{service:s}'\n\nRecent service logs:{logs:s}", "service_reload_or_restart_failed": "Could not reload or restart the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_reloaded_or_restarted": "'{service:s}' service reloaded or restarted", "service_reloaded_or_restarted": "The '{service:s}' service was reloaded or restarted",
"service_start_failed": "Could not start the service '{service:s}'\n\nRecent service logs:{logs:s}", "service_start_failed": "Could not start the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_started": "'{service:s}' service started", "service_started": "'{service:s}' service started",
"service_stop_failed": "Could not stop the service '{service:s}'\n\nRecent service logs:{logs:s}", "service_stop_failed": "Could not stop the service '{service:s}'\n\nRecent service logs:{logs:s}",
"service_stopped": "'{service:s}' service stopped", "service_stopped": "The '{service:s}' service stopped",
"service_unknown": "Unknown service '{service:s}'", "service_unknown": "Unknown service '{service:s}'",
"ssowat_conf_generated": "SSOwat configuration generated", "ssowat_conf_generated": "SSOwat configuration generated",
"ssowat_conf_updated": "SSOwat configuration updated", "ssowat_conf_updated": "SSOwat configuration updated",
"ssowat_persistent_conf_read_error": "Could not read persistent SSOwat configuration: {error:s}. Edit /etc/ssowat/conf.json.persistent file to fix the JSON syntax",
"ssowat_persistent_conf_write_error": "Could not save persistent SSOwat configuration: {error:s}. Edit /etc/ssowat/conf.json.persistent file to fix the JSON syntax",
"system_upgraded": "System upgraded", "system_upgraded": "System upgraded",
"system_username_exists": "Username already exists in the list of system users", "system_username_exists": "Username already exists in the list of system users",
"this_action_broke_dpkg": "This action broke dpkg/APT (the system package managers)… You can try to solve this issue by connecting through SSH and running `sudo dpkg --configure -a`.", "this_action_broke_dpkg": "This action broke dpkg/APT (the system package managers)… You can try to solve this issue by connecting through SSH and running `sudo dpkg --configure -a`.",
@ -515,11 +524,11 @@
"tools_upgrade_at_least_one": "Please specify '--apps', or '--system'", "tools_upgrade_at_least_one": "Please specify '--apps', or '--system'",
"tools_upgrade_cant_both": "Cannot upgrade both system and apps at the same time", "tools_upgrade_cant_both": "Cannot upgrade both system and apps at the same time",
"tools_upgrade_cant_hold_critical_packages": "Could not hold critical packages…", "tools_upgrade_cant_hold_critical_packages": "Could not hold critical packages…",
"tools_upgrade_cant_unhold_critical_packages": "Could not to unhold critical packages…", "tools_upgrade_cant_unhold_critical_packages": "Could not unhold critical packages…",
"tools_upgrade_regular_packages": "Now upgrading 'regular' (non-yunohost-related) packages…", "tools_upgrade_regular_packages": "Now upgrading 'regular' (non-yunohost-related) packages…",
"tools_upgrade_regular_packages_failed": "Could not upgrade packages: {packages_list}", "tools_upgrade_regular_packages_failed": "Could not upgrade packages: {packages_list}",
"tools_upgrade_special_packages": "Now upgrading 'special' (yunohost-related) packages…", "tools_upgrade_special_packages": "Now upgrading 'special' (yunohost-related) packages…",
"tools_upgrade_special_packages_explanation": "This action will end, but the actual special upgrade will continue in background. Please don't start any other action on your server in the next ~10 minutes (depending on your hardware speed). Once it i done, you may have to log in on the webadmin page again. The upgrade log will be available in Tools → Log (on the webadmin page) or through 'yunohost log list' (from the command line).", "tools_upgrade_special_packages_explanation": "This action will end, but the actual special upgrade will continue in background. Please don't start any other actions on your server the next ~10 minutes (depending on hardware speed). Once done, you may have to log in on the webadmin page again. The upgrade log will be available in Tools → Log (on the webadmin page) or through 'yunohost log list' (from the command-line).",
"tools_upgrade_special_packages_completed": "YunoHost package upgrade completed.\nPress [Enter] to get the command line back", "tools_upgrade_special_packages_completed": "YunoHost package upgrade completed.\nPress [Enter] to get the command line back",
"unbackup_app": "App '{app:s}' will not be saved", "unbackup_app": "App '{app:s}' will not be saved",
"unexpected_error": "Something unexpected went wrong: {error}", "unexpected_error": "Something unexpected went wrong: {error}",
@ -529,14 +538,14 @@
"update_apt_cache_failed": "Could not to update the cache of APT (Debian's package manager). Here is a dump of the sources.list lines, which might help identify problematic lines: \n{sourceslist}", "update_apt_cache_failed": "Could not to update the cache of APT (Debian's package manager). Here is a dump of the sources.list lines, which might help identify problematic lines: \n{sourceslist}",
"update_apt_cache_warning": "Something went wrong while updating the cache of APT (Debian's package manager). Here is a dump of the sources.list lines, which might help identify problematic lines: \n{sourceslist}", "update_apt_cache_warning": "Something went wrong while updating the cache of APT (Debian's package manager). Here is a dump of the sources.list lines, which might help identify problematic lines: \n{sourceslist}",
"updating_apt_cache": "Fetching available upgrades for system packages…", "updating_apt_cache": "Fetching available upgrades for system packages…",
"updating_app_lists": "Fetching available upgrades for applications…", "updating_app_lists": "Fetching available upgrades for apps…",
"upgrade_complete": "Upgrade complete", "upgrade_complete": "Upgrade complete",
"upgrading_packages": "Upgrading packages…", "upgrading_packages": "Upgrading packages…",
"upnp_dev_not_found": "No UPnP device found", "upnp_dev_not_found": "No UPnP device found",
"upnp_disabled": "UPnP turned off", "upnp_disabled": "UPnP turned off",
"upnp_enabled": "UPnP turned on", "upnp_enabled": "UPnP turned on",
"upnp_port_open_failed": "Could not open port via UPnP", "upnp_port_open_failed": "Could not open port via UPnP",
"user_already_exists": "User {user} already exists", "user_already_exists": "The user '{user}' already exists",
"user_created": "User created", "user_created": "User created",
"user_creation_failed": "Could not create user {user}: {error}", "user_creation_failed": "Could not create user {user}: {error}",
"user_deleted": "User deleted", "user_deleted": "User deleted",
@ -550,7 +559,7 @@
"yunohost_already_installed": "YunoHost is already installed", "yunohost_already_installed": "YunoHost is already installed",
"yunohost_ca_creation_failed": "Could not create certificate authority", "yunohost_ca_creation_failed": "Could not create certificate authority",
"yunohost_ca_creation_success": "Local certification authority created.", "yunohost_ca_creation_success": "Local certification authority created.",
"yunohost_configured": "YunoHost now configured", "yunohost_configured": "YunoHost is now configured",
"yunohost_installing": "Installing YunoHost…", "yunohost_installing": "Installing YunoHost…",
"yunohost_not_installed": "YunoHost is incorrectly or not correctly installed. Please run 'yunohost tools postinstall'" "yunohost_not_installed": "YunoHost is not correctly installed. Please run 'yunohost tools postinstall'"
} }

View file

@ -40,7 +40,7 @@
"app_argument_choice_invalid": "Uzu unu el ĉi tiuj elektoj '{choices:s}' por la argumento '{name:s}'", "app_argument_choice_invalid": "Uzu unu el ĉi tiuj elektoj '{choices:s}' por la argumento '{name:s}'",
"app_argument_invalid": "Elektu validan valoron por la argumento '{name:s}': {error:s}", "app_argument_invalid": "Elektu validan valoron por la argumento '{name:s}': {error:s}",
"app_change_url_failed_nginx_reload": "Ne eblis reŝarĝi NGINX. Jen la eligo de 'nginx -t':\n{nginx_errors:s}", "app_change_url_failed_nginx_reload": "Ne eblis reŝarĝi NGINX. Jen la eligo de 'nginx -t':\n{nginx_errors:s}",
"appslist_url_already_tracked": "Estas jam registrita aplika listo kun la URL {url:s}.", "appslist_url_already_tracked": "Jam ekzistas registrita app-listo kun la URL {url:s}.",
"ask_new_admin_password": "Nova administrada pasvorto", "ask_new_admin_password": "Nova administrada pasvorto",
"app_action_broke_system": "Ĉi tiu ago ŝajne rompis ĉi tiujn gravajn servojn: {services}", "app_action_broke_system": "Ĉi tiu ago ŝajne rompis ĉi tiujn gravajn servojn: {services}",
"app_unsupported_remote_type": "Malkontrolita fora speco uzita por la apliko", "app_unsupported_remote_type": "Malkontrolita fora speco uzita por la apliko",
@ -50,16 +50,16 @@
"backup_abstract_method": "Ĉi tiu rezerva metodo ankoraŭ efektiviĝis", "backup_abstract_method": "Ĉi tiu rezerva metodo ankoraŭ efektiviĝis",
"apps_already_up_to_date": "Ĉiuj aplikoj estas jam ĝisdatigitaj", "apps_already_up_to_date": "Ĉiuj aplikoj estas jam ĝisdatigitaj",
"backup_borg_not_implemented": "La kopia metodo de Borg ankoraŭ ne estas efektivigita", "backup_borg_not_implemented": "La kopia metodo de Borg ankoraŭ ne estas efektivigita",
"app_upgrade_stopped": "La ĝisdatigo de ĉiuj aplikoj estis ĉesigita por eviti eblajn damaĝojn ĉar la antaŭa apliko ne sukcesis ĝisdatigi", "app_upgrade_stopped": "Ĝisdatigi ĉiujn aplikaĵojn estis ĉesigita por eviti eblajn damaĝojn ĉar unu app ne povis esti altgradigita",
"app_location_unavailable": "Ĉi tiu URL aŭ ne haveblas, aŭ konfliktas kun la jam instalita (j) apliko (j):\n{apps:s}", "app_location_unavailable": "Ĉi tiu URL aŭ ne haveblas, aŭ konfliktas kun la jam instalita (j) apliko (j):\n{apps:s}",
"backup_archive_app_not_found": "Ne povis trovi la programon '{app:s}' en la rezerva ar archiveivo", "backup_archive_app_not_found": "Ne povis trovi la programon '{app:s}' en la rezerva ar archiveivo",
"backup_actually_backuping": "Krei rezervan ar archiveivon el la kolektitaj dosieroj …", "backup_actually_backuping": "Krei rezervan ar archiveivon el la kolektitaj dosieroj …",
"backup_method_borg_finished": "Sekurkopio en Borg finiĝis", "backup_method_borg_finished": "Sekurkopio en Borg finiĝis",
"appslist_removed": "{appslist:s} aplika listo forigita", "appslist_removed": "La listo de '{appslist:s}' estis forigita",
"app_change_url_no_script": "Ĉi tiu apliko '{app_name:s}' ankoraŭ ne subtenas URL-modifon. Eble vi devus altgradigi ĝin.", "app_change_url_no_script": "La app '{app_name:s}' ankoraŭ ne subtenas URL-modifon. Eble vi devus altgradigi ĝin.",
"app_start_install": "Instalanta aplikon {app} …", "app_start_install": "Instali la programon '{app}' …",
"backup_created": "Sekurkopio kreita", "backup_created": "Sekurkopio kreita",
"app_make_default_location_already_used": "Ne povas igi la aplikon '{app}' defaŭlta sur la domajno, {domain} jam uziĝas de la alia app '{other_app}'", "app_make_default_location_already_used": "Ne povas igi la aplikon '{app}' defaŭlta sur la domajno, '{domain}' jam uziĝas de la alia app '{other_app}'",
"backup_method_copy_finished": "Rezerva kopio finis", "backup_method_copy_finished": "Rezerva kopio finis",
"app_not_properly_removed": "{app:s} ne estis ĝuste forigita", "app_not_properly_removed": "{app:s} ne estis ĝuste forigita",
"backup_archive_broken_link": "Ne povis aliri la rezervan ar archiveivon (rompita ligilo al {path:s})", "backup_archive_broken_link": "Ne povis aliri la rezervan ar archiveivon (rompita ligilo al {path:s})",
@ -78,15 +78,15 @@
"backup_custom_backup_error": "Propra rezerva metodo ne povis preterpasi la paŝon \"sekurkopio\"", "backup_custom_backup_error": "Propra rezerva metodo ne povis preterpasi la paŝon \"sekurkopio\"",
"ask_main_domain": "Ĉefa domajno", "ask_main_domain": "Ĉefa domajno",
"backup_method_tar_finished": "TAR-rezerva ar archiveivo kreita", "backup_method_tar_finished": "TAR-rezerva ar archiveivo kreita",
"appslist_unknown": "Aplika listo {appslist:s} nekonata.", "appslist_unknown": "La app-listo '{appslist:s}' estas nekonata.",
"ask_list_to_remove": "Listo por forigi", "ask_list_to_remove": "Listo por forigi",
"backup_cant_mount_uncompress_archive": "Ne povis munti la nekompresitan ar archiveivon kiel protektita kontraŭ skribo", "backup_cant_mount_uncompress_archive": "Ne povis munti la nekompresitan ar archiveivon kiel protektita kontraŭ skribo",
"appslist_retrieve_bad_format": "Ne povis legi la elprenitan liston {appslist:s}", "appslist_retrieve_bad_format": "Ne povis legi la elprenitan liston '{appslist:s}'",
"appslist_corrupted_json": "Ne povis ŝarĝi la aplikajn listojn. Ĝi aspektas kiel {filename:s} estas damaĝita.", "appslist_corrupted_json": "Ne povis ŝarĝi la aplikajn listojn. Ĝi aspektas kiel {filename:s} estas damaĝita.",
"app_action_cannot_be_ran_because_required_services_down": "Ĉi tiu app postulas iujn servojn, kiuj nuntempe malleviĝas. Antaŭ ol daŭrigi, vi provu rekomenci la jenajn servojn (kaj eventuale esploru kial ili malsukcesas): {services}", "app_action_cannot_be_ran_because_required_services_down": "Ĉi tiuj postulataj servoj devas funkcii por funkciigi ĉi tiun agon: {services}. Provu rekomenci ilin por daŭrigi (kaj eble esploru, kial ili malsupreniras).",
"backup_copying_to_organize_the_archive": "Kopiante {size:s} MB por organizi la ar archiveivon", "backup_copying_to_organize_the_archive": "Kopiante {size:s} MB por organizi la ar archiveivon",
"backup_output_directory_forbidden": "Elektu malsaman elirejan dosierujon. Sekurkopioj ne povas esti kreitaj en sub-dosierujoj / bin, / boot, / dev, / ktp, / lib, / root, / run, / sbin, / sys, / usr, / var aŭ /home/yunohost.backup/archives", "backup_output_directory_forbidden": "Elektu malsaman elirejan dosierujon. Sekurkopioj ne povas esti kreitaj en sub-dosierujoj / bin, / boot, / dev, / ktp, / lib, / root, / run, / sbin, / sys, / usr, / var aŭ /home/yunohost.backup/archives",
"appslist_could_not_migrate": "Ne povis migri la liston de aplikoj {appslist:s}! Ne eblis analizi la URL ... La malnova cron-laboro konserviĝis en {bkp_file:s}.", "appslist_could_not_migrate": "Ne povis migri la liston de aplikoj '{appslist:s}'! Ne eblis analizi la URL ... La malnova cron-laboro konserviĝis en {bkp_file:s}.",
"app_requirements_failed": "Certaines exigences ne sont pas remplies pour {app}: {error}", "app_requirements_failed": "Certaines exigences ne sont pas remplies pour {app}: {error}",
"backup_no_uncompress_archive_dir": "Ne ekzistas tia nekompremita arkiva dosierujo", "backup_no_uncompress_archive_dir": "Ne ekzistas tia nekompremita arkiva dosierujo",
"password_too_simple_1": "Pasvorto devas esti almenaŭ 8 signojn longa", "password_too_simple_1": "Pasvorto devas esti almenaŭ 8 signojn longa",
@ -94,11 +94,11 @@
"app_upgrade_several_apps": "La sekvaj apliko estos altgradigitaj: {apps}", "app_upgrade_several_apps": "La sekvaj apliko estos altgradigitaj: {apps}",
"backup_archive_open_failed": "Ne povis malfermi la rezervan ar archiveivon", "backup_archive_open_failed": "Ne povis malfermi la rezervan ar archiveivon",
"ask_lastname": "Familia nomo", "ask_lastname": "Familia nomo",
"app_start_backup": "Kolekti dosierojn por esti subtenata por {app} …", "app_start_backup": "Kolekti dosierojn por esti subtenata por la '{app}' …",
"backup_archive_name_exists": "Rezerva arkivo kun ĉi tiu nomo jam ekzistas.", "backup_archive_name_exists": "Rezerva arkivo kun ĉi tiu nomo jam ekzistas.",
"backup_applying_method_tar": "Krei la rezervan TAR-ar archiveivon …", "backup_applying_method_tar": "Krei la rezervan TAR-ar archiveivon …",
"backup_method_custom_finished": "Propra rezerva metodo '{metodo:s}' finiĝis", "backup_method_custom_finished": "Propra rezerva metodo '{metodo:s}' finiĝis",
"appslist_retrieve_error": "Ne eblas retrovi la forajn aplikajn listojn {appslist:s}: {eraro:s}", "appslist_retrieve_error": "Ne eblas akiri la forajn listojn '{appslist:s}': {eraro:s}",
"app_already_installed_cant_change_url": "Ĉi tiu app estas jam instalita. La URL ne povas esti ŝanĝita nur per ĉi tiu funkcio. Rigardu \"app changeurl\" se ĝi haveblas.", "app_already_installed_cant_change_url": "Ĉi tiu app estas jam instalita. La URL ne povas esti ŝanĝita nur per ĉi tiu funkcio. Rigardu \"app changeurl\" se ĝi haveblas.",
"app_not_correctly_installed": "{app:s} ŝajnas esti malĝuste instalita", "app_not_correctly_installed": "{app:s} ŝajnas esti malĝuste instalita",
"app_removed": "{app:s} forigita", "app_removed": "{app:s} forigita",
@ -106,27 +106,27 @@
"app_package_need_update": "La pakaĵo {app} devas esti ĝisdatigita por sekvi YunoHost-ŝanĝojn", "app_package_need_update": "La pakaĵo {app} devas esti ĝisdatigita por sekvi YunoHost-ŝanĝojn",
"backup_nothings_done": "Nenio por ŝpari", "backup_nothings_done": "Nenio por ŝpari",
"backup_applying_method_custom": "Nomante la kutiman rezervan metodon '{metodo:s}' …", "backup_applying_method_custom": "Nomante la kutiman rezervan metodon '{metodo:s}' …",
"appslist_fetched": "Ĝisdatigita aplika listo {appslist:s} elprenita", "appslist_fetched": "Ĝisdatigis la liston de aplikoj '{appslist:s}'",
"backup_app_failed": "Ne eblis rezervi la programon '{app:s}'", "backup_app_failed": "Ne eblis rezervi la programon '{app:s}'",
"app_upgrade_some_app_failed": "Iuj aplikoj ne povis esti altgradigitaj", "app_upgrade_some_app_failed": "Iuj aplikoj ne povis esti altgradigitaj",
"app_start_remove": "Forigo de apliko {app} …", "app_start_remove": "Forigo de la apliko '{app}' …",
"backup_output_directory_not_empty": "Vi devas elekti malplenan eligitan dosierujon", "backup_output_directory_not_empty": "Vi devas elekti malplenan eligitan dosierujon",
"backup_archive_writing_error": "Ne povis aldoni la dosierojn '{source:s}' (nomitaj en la ar theivo '{dest:s}') por esti rezervitaj en la kunpremita arkivo '{archive:s}'", "backup_archive_writing_error": "Ne povis aldoni la dosierojn '{source:s}' (nomitaj en la ar theivo '{dest:s}') por esti rezervitaj en la kunpremita arkivo '{archive:s}'",
"ask_email": "Retpoŝta adreso", "ask_email": "Retpoŝta adreso",
"app_start_restore": "Restarigi aplikon {app} …", "app_start_restore": "Restarigi la programon '{app}' …",
"backup_applying_method_copy": "Kopiante ĉiujn dosierojn al sekurkopio …", "backup_applying_method_copy": "Kopiante ĉiujn dosierojn al sekurkopio …",
"backup_couldnt_bind": "Ne povis ligi {src:s} al {dest:s}.", "backup_couldnt_bind": "Ne povis ligi {src:s} al {dest:s}.",
"ask_password": "Pasvorto", "ask_password": "Pasvorto",
"app_requirements_unmeet": "Postuloj ne estas renkontitaj por {app}, la pakaĵo {pkgname} ({version}) devas esti {spec}", "app_requirements_unmeet": "Postuloj ne estas renkontitaj por {app}, la pakaĵo {pkgname} ({version}) devas esti {spec}",
"ask_firstname": "Antaŭnomo", "ask_firstname": "Antaŭnomo",
"backup_ask_for_copying_if_needed": "Iuj dosieroj ne povus esti pretigitaj por sekurkopio uzante la metodon, kiu evitas portempe malŝpari spacon en la sistemo. Por plenumi la sekurkopion, {size:s} MB estos provizore. Ĉu vi konsentas?", "backup_ask_for_copying_if_needed": "Ĉu vi volas realigi la sekurkopion uzante {size:s} MB provizore? (Ĉi tiu maniero estas uzata ĉar iuj dosieroj ne povus esti pretigitaj per pli efika metodo.)",
"backup_mount_archive_for_restore": "Preparante arkivon por restarigo …", "backup_mount_archive_for_restore": "Preparante arkivon por restarigo …",
"appslist_migrating": "Migra aplika listo {appslist:s} …", "appslist_migrating": "Migrado de la aplika listo '{appslist:s}' …",
"backup_csv_creation_failed": "Ne povis krei la CSV-dosieron bezonatan por restarigo", "backup_csv_creation_failed": "Ne povis krei la CSV-dosieron bezonatan por restarigo",
"backup_archive_name_unknown": "Nekonata loka rezerva ar archiveivo nomata '{name:s}'", "backup_archive_name_unknown": "Nekonata loka rezerva ar archiveivo nomata '{name:s}'",
"backup_applying_method_borg": "Sendado de ĉiuj dosieroj al sekurkopio en borg-rezerva deponejo …", "backup_applying_method_borg": "Sendado de ĉiuj dosieroj al sekurkopio en borg-rezerva deponejo …",
"app_sources_fetch_failed": "Ne povis akiri fontajn dosierojn, ĉu la URL estas ĝusta?", "app_sources_fetch_failed": "Ne povis akiri fontajn dosierojn, ĉu la URL estas ĝusta?",
"appslist_name_already_tracked": "Registrita aplika listo kun nomo {name:s} jam ekzistas.", "appslist_name_already_tracked": "Registrita aplika listo kun la nomo {name:s} jam ekzistas.",
"ask_new_domain": "Nova domajno", "ask_new_domain": "Nova domajno",
"app_unknown": "Nekonata apliko", "app_unknown": "Nekonata apliko",
"app_not_upgraded": "La aplikaĵo '{failed_app}' ne ĝisdatigis, kaj pro tio la sekvaj ĝisdatigoj de aplikoj estis nuligitaj: {apps}", "app_not_upgraded": "La aplikaĵo '{failed_app}' ne ĝisdatigis, kaj pro tio la sekvaj ĝisdatigoj de aplikoj estis nuligitaj: {apps}",
@ -134,5 +134,434 @@
"ask_path": "Pado", "ask_path": "Pado",
"app_upgraded": "{app:s} altgradigita", "app_upgraded": "{app:s} altgradigita",
"backup_deleted": "Rezerva forigita", "backup_deleted": "Rezerva forigita",
"backup_csv_addition_failed": "Ne povis aldoni dosierojn al sekurkopio en la CSV-dosiero" "backup_csv_addition_failed": "Ne povis aldoni dosierojn al sekurkopio en la CSV-dosiero",
"dpkg_lock_not_available": "Ĉi tiu komando ne povas funkcii nun ĉar alia programo uzas la seruron de dpkg (la administrilo de paka sistemo)",
"migration_0003_yunohost_upgrade": "Komenci la ĝisdatigon de YunoHost-pako ... La migrado finiĝos, sed la efektiva ĝisdatigo okazos tuj poste. Post kiam la operacio finiĝos, vi eble devos ensaluti denove sur la retpaĝo.",
"domain_dyndns_root_unknown": "Nekonata radika domajno DynDNS",
"field_invalid": "Nevalida kampo '{:s}'",
"log_app_makedefault": "Faru '{}' la defaŭlta apliko",
"migration_0003_still_on_jessie_after_main_upgrade": "Io okazis malbone dum la ĉefa ĝisdatigo: Ĉu la sistemo ankoraŭ estas en Jessie‽ Por esplori la aferon, bonvolu rigardi {log}:s …",
"migration_0011_can_not_backup_before_migration": "La sekurkopio de la sistemo antaŭ la migrado malsukcesis. Migrado malsukcesis. Eraro: {error:s}",
"migration_0011_create_group": "Krei grupon por ĉiu uzanto…",
"backup_system_part_failed": "Ne eblis sekurkopi la sistemon de '{part:s}'",
"global_settings_setting_security_postfix_compatibility": "Kongruo vs sekureca kompromiso por la Postfix-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"group_unknown": "La grupo '{group:s}' estas nekonata",
"mailbox_disabled": "Retpoŝto malŝaltita por uzanto {user:s}",
"migration_description_0011_setup_group_permission": "Agordu uzantogrupon kaj starigu permeson por programoj kaj servoj",
"migration_0011_backup_before_migration": "Krei sekurkopion de LDAP-datumbazo kaj agordojn antaŭ la efektiva migrado.",
"migration_0011_LDAP_config_dirty": "Similas ke vi agordis vian LDAP-agordon. Por ĉi tiu migrado la LDAP-agordo bezonas esti ĝisdatigita.\nVi devas konservi vian aktualan agordon, reintaligi la originalan agordon per funkciado de \"yunohost iloj regen-conf -f\" kaj reprovi la migradon",
"migration_0011_migrate_permission": "Migrado de permesoj de agordoj al aplikoj al LDAP…",
"migration_0011_migration_failed_trying_to_rollback": "Migrado malsukcesis ... provante reverti la sistemon.",
"migrations_dependencies_not_satisfied": "Ne eblas kuri migradon {id} ĉar unue vi devas ruli ĉi tiujn migradojn: {dependencies_id}",
"migrations_failed_to_load_migration": "Ne povis ŝarĝi migradon {id}: {error}",
"migrations_exclusive_options": "'--auto', '--skip' kaj '--force-rerun' estas reciproke ekskluzivaj ebloj.",
"migrations_must_provide_explicit_targets": "Vi devas provizi eksplicitajn celojn kiam vi uzas '--skip' aŭ '--force-rerun'",
"permission_update_failed": "Ne povis ĝisdatigi permeson '{permission}': {error}",
"permission_updated": "Ĝisdatigita \"{permission:s}\" rajtigita",
"permission_update_nothing_to_do": "Neniuj permesoj ĝisdatigi",
"tools_upgrade_cant_hold_critical_packages": "Ne povis teni kritikajn pakojn…",
"upnp_dev_not_found": "Neniu UPnP-aparato trovita",
"migration_description_0012_postgresql_password_to_md5_authentication": "Devigu PostgreSQL-aŭtentigon uzi MD5 por lokaj ligoj",
"migration_0011_done": "Migrado sukcesis. Vi nun kapablas administri uzantajn grupojn.",
"migration_0011_LDAP_update_failed": "Ne povis ĝisdatigi LDAP. Eraro: {error:s}",
"pattern_password": "Devas esti almenaŭ 3 signoj longaj",
"root_password_desynchronized": "La pasvorta administranto estis ŝanĝita, sed YunoHost ne povis propagandi ĉi tion al la radika pasvorto!",
"service_remove_failed": "Ne povis forigi la servon '{service:s}'",
"migration_0003_fail2ban_upgrade": "Komenci la ĝisdatigon Fail2Ban…",
"backup_permission": "Rezerva permeso por app {app:s}",
"log_user_group_delete": "Forigi grupon '{}'",
"log_user_group_update": "Ĝisdatigi grupon '{}'",
"migration_0005_postgresql_94_not_installed": "PostgreSQL ne estis instalita en via sistemo. Nenio por fari.",
"dyndns_provider_unreachable": "Ne povas atingi Dyndns-provizanton {provider}: ĉu via YunoHost ne estas ĝuste konektita al la interreto aŭ la dynette-servilo malŝaltiĝas.",
"good_practices_about_user_password": "Vi nun estas por difini novan uzantan pasvorton. La pasvorto devas esti almenaŭ 8 signoj - kvankam estas bone praktiki uzi pli longan pasvorton (t.e. pasfrazon) kaj / aŭ variaĵon de signoj (majuskloj, minuskloj, ciferoj kaj specialaj signoj).",
"group_updated": "Ĝisdatigita \"{group}\" grupo",
"group_already_exist": "Grupo {group} jam ekzistas",
"group_already_exist_on_system": "Grupo {group} jam ekzistas en la sistemaj grupoj",
"group_cannot_be_edited": "La grupo {group} ne povas esti redaktita permane.",
"group_cannot_be_deleted": "La grupo {group} ne povas esti forigita permane.",
"group_update_failed": "Ne povis ĝisdatigi la grupon '{group}': {error}",
"group_user_already_in_group": "Uzanto {user} jam estas en grupo {group}",
"group_user_not_in_group": "Uzanto {user} ne estas en grupo {group}",
"installation_complete": "Kompleta instalado",
"log_category_404": "La loga kategorio '{category}' ne ekzistas",
"log_permission_create": "Krei permeson '{}'",
"log_permission_delete": "Forigi permeson '{}'",
"log_permission_urls": "Ĝisdatigu URLojn rilatajn al permeso '{}'",
"log_user_group_create": "Krei grupon '{}'",
"log_user_permission_update": "Mise à jour des accès pour la permission '{}'",
"log_user_permission_reset": "Restarigi permeson '{}'",
"mail_forward_remove_failed": "Ne povis forigi retpoŝton plusendante '{mail:s}'",
"migration_0011_rollback_success": "Sistemo ruliĝis reen.",
"migration_0011_update_LDAP_database": "Ĝisdatigante LDAP-datumbazon…",
"migration_0011_update_LDAP_schema": "Ĝisdatigante LDAP-skemon…",
"migration_0011_failed_to_remove_stale_object": "Malsukcesis forigi neokazan objekton {dn}: {error}",
"migrations_already_ran": "Tiuj migradoj estas jam faritaj: {ids}",
"migrations_no_such_migration": "Estas neniu migrado nomata {id}",
"permission_already_allowed": "Grupo '{group}' jam havas permeson '{permission}' ebligita'",
"permission_already_disallowed": "Grupo '{group}' jam havas permeson '{permission}' malebligita'",
"permission_cannot_remove_main": "Forigo de ĉefa permeso ne rajtas",
"permission_creation_failed": "Ne povis krei permeson '{permission}': {error}",
"tools_update_failed_to_app_fetchlist": "Ne povis ĝisdatigi la aparatojn de YunoHost ĉar: {error}",
"user_already_exists": "Uzanto {uzanto} jam ekzistas",
"migrations_pending_cant_rerun": "Tiuj migradoj ankoraŭ estas pritraktataj, do ne plu rajtas esti ekzekutitaj: {ids}",
"migrations_running_forward": "Kuranta migrado {id}…",
"migrations_success_forward": "Migrado {id} kompletigita",
"operation_interrupted": "La operacio estis permane interrompita?",
"permission_created": "Permesita '{permission:s}' kreita",
"permission_deleted": "Permesita \"{permission:s}\" forigita",
"permission_deletion_failed": "Ne povis forigi permeson '{permission}': {error}",
"permission_not_found": "Permesita \"{permission:s}\" ne trovita",
"restore_not_enough_disk_space": "Ne sufiĉa spaco (spaco: {free_space:d} B, necesa spaco: {needed_space:d} B, sekureca marĝeno: {margin:d} B)",
"tools_upgrade_regular_packages": "Nun ĝisdatigi 'regulajn' (ne-yunohost-rilatajn) pakojn …",
"tools_upgrade_special_packages_explanation": "Ĉi tiu ago finiĝos, sed la fakta speciala ĝisdatigo daŭros en fono. Bonvolu ne komenci iun alian agon en via servilo en la sekvaj ~ 10 minutoj (depende de via aparata rapideco). Unufoje mi plenumis, vi eble devos ensaluti en la retpaĝo. La ĝisdatiga registro estos havebla en Iloj → Madero (sur la retpaĝo) aŭ tra 'yunohost-registro-listo' (el la komandlinio).",
"unrestore_app": "App '{app:s}' ne restarigos",
"group_created": "Grupo '{group}' kreita",
"group_creation_failed": "Ne povis krei la grupon '{group}': {error}",
"group_deleted": "Grupo '{group}' forigita",
"group_deletion_failed": "Ne povis forigi la grupon '{group}': {error}",
"migrations_not_pending_cant_skip": "Tiuj migradoj ankoraŭ ne estas pritraktataj, do ne eblas preterlasi: {ids}",
"permission_already_exist": "Permesita '{permission}' jam ekzistas",
"domain_created": "Domajno kreita",
"migrate_tsig_wait_2": "2 minutoj …",
"log_user_create": "Aldonu uzanton '{}'",
"ip6tables_unavailable": "Vi ne povas ludi kun ip6tabloj ĉi tie. Vi estas en ujo aŭ via kerno ne subtenas ĝin",
"mail_unavailable": "Ĉi tiu retpoŝta adreso estas rezervita kaj aŭtomate estos atribuita al la unua uzanto",
"certmanager_domain_dns_ip_differs_from_public_ip": "La DNS 'A' rekordo por la domajno '{domain:s}' diferencas de ĉi tiu IP-servilo. Se vi lastatempe modifis vian A-registron, bonvolu atendi ĝin propagandi (iuj DNS-disvastigaj kontroliloj estas disponeblaj interrete). (Se vi scias, kion vi faras, uzu '--no-checks' por malŝalti tiujn ĉekojn.)",
"tools_upgrade_special_packages_completed": "Plenumis la ĝisdatigon de pakaĵoj de YunoHost.\nPremu [Enter] por retrovi la komandlinion",
"log_remove_on_failed_install": "Forigu '{}' post malsukcesa instalado",
"regenconf_file_manually_modified": "La agorddosiero '{conf}' estis modifita permane kaj ne estos ĝisdatigita",
"regenconf_would_be_updated": "La agordo estus aktualigita por la kategorio '{category}'",
"certmanager_cert_install_success_selfsigned": "Mem-subskribita atestilo nun instalita por la domajno '{domain:s}'",
"global_settings_unknown_setting_from_settings_file": "Nekonata ŝlosilo en agordoj: '{setting_key:s}', forĵetu ĝin kaj konservu ĝin en /etc/yunohost/settings-unknown.json",
"regenconf_file_backed_up": "Agordodosiero '{conf}' estis rezervita al '{backup}'",
"migration_0007_cannot_restart": "SSH ne rekomencas post provi nuligi la migradan numeron 6.",
"migration_description_0006_sync_admin_and_root_passwords": "Sinkronigu admin kaj radikajn pasvortojn",
"updating_app_lists": "Akirante haveblajn ĝisdatigojn por aplikoj…",
"iptables_unavailable": "Vi ne povas ludi kun iptables ĉi tie. Vi estas en ujo aŭ via kerno ne subtenas ĝin",
"global_settings_cant_write_settings": "Ne eblis konservi agordojn, tial: {reason:s}",
"service_added": "La servo '{service:s}' aldonis",
"upnp_disabled": "UPnP malŝaltis",
"service_started": "Servo '{service:s}' komenciĝis",
"port_already_opened": "Haveno {port:d} estas jam malfermita por {ip_version:s} rilatoj",
"installation_failed": "Io okazis malbone kun la instalado",
"network_check_mx_ko": "DNS MX-rekordo ne estas agordita",
"migrate_tsig_wait_3": "1 minuto …",
"certmanager_conflicting_nginx_file": "Ne povis prepari domajnon por ACME-defio: la agordo de NGINX {filepath:s} konfliktas kaj unue devas esti forigita",
"upgrading_packages": "Ĝisdatigi pakojn…",
"custom_app_url_required": "Vi devas provizi URL por altgradigi vian kutimon app {app: s}",
"service_reload_failed": "Ne povis reŝargi la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"packages_upgrade_failed": "Ne povis ĝisdatigi ĉiujn pakojn",
"hook_json_return_error": "Ne povis legi revenon de hoko {path:s}. Eraro: {msg:s}. Kruda enhavo: {raw_content}",
"dyndns_cron_removed": "DynDNS cron-laboro forigita",
"dyndns_key_not_found": "DNS-ŝlosilo ne trovita por la domajno",
"custom_appslist_name_required": "Vi devas doni nomon por via kutima app-listo",
"tools_upgrade_regular_packages_failed": "Ne povis ĝisdatigi pakojn: {packages_list}",
"service_start_failed": "Ne povis komenci la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"service_reloaded": "Servo '{service:s}' reŝargita",
"system_upgraded": "Sistemo ĝisdatigita",
"domain_deleted": "Domajno forigita",
"certmanager_acme_not_configured_for_domain": "Atestilo por la domajno '{domain:s}' ne ŝajnas esti ĝuste instalita. Bonvolu ekzekuti 'cert-instali' por ĉi tiu regado unue.",
"migration_description_0009_decouple_regenconf_from_services": "Malkonstruu la regen-konf-mekanismon de servoj",
"user_update_failed": "Ne povis ĝisdatigi uzanton {user}: {error}",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "Lasu la SSH-agordon estu administrata de YunoHost (paŝo 2, manlibro)",
"restore_confirm_yunohost_installed": "Ĉu vi vere volas restarigi jam instalitan sistemon? [{answers:s}]",
"pattern_positive_number": "Devas esti pozitiva nombro",
"monitor_stats_file_not_found": "Statistika dosiero ne trovita",
"certmanager_error_no_A_record": "Neniu DNS 'A' rekordo trovita por '{domain:s}'. Vi bezonas atentigi vian domajnan nomon al via maŝino por povi instali atestilon Lasu-Ĉifri. (Se vi scias, kion vi faras, uzu '--no-checks' por malŝalti tiujn ĉekojn.)",
"update_apt_cache_failed": "Ne eblis ĝisdatigi la kaŝmemoron de APT (paka administranto de Debian). Jen rubujo de la sources.list-linioj, kiuj povus helpi identigi problemajn liniojn:\n{sourcelist}",
"migrations_no_migrations_to_run": "Neniuj migradoj por funkcii",
"executing_command": "Plenumanta komandon '{command:s}' …",
"diagnosis_no_apps": "Neniu tia instalita app",
"certmanager_attempt_to_renew_nonLE_cert": "La atestilo por la domajno '{domain:s}' ne estas elsendita de Let's Encrypt. Ne eblas renovigi ĝin aŭtomate!",
"global_settings_setting_example_bool": "Ekzemplo bulea elekto",
"domain_dyndns_already_subscribed": "Vi jam abonis DynDNS-domajnon",
"log_letsencrypt_cert_renew": "Renovigu '{}' Let's Encrypt atestilon",
"migrate_tsig_start": "Detektita ŝlosila algoritmo nesufiĉa por TSIG-subskribo de la domajno '{domain}', komencanta migradon al la pli sekura HMAC-SHA-512",
"ldap_init_failed_to_create_admin": "LDAP-iniciato ne povis krei administran uzanton",
"backup_output_directory_required": "Vi devas provizi elirejan dosierujon por la sekurkopio",
"tools_upgrade_cant_unhold_critical_packages": "Ne povis malhelpi kritikajn pakojn…",
"diagnosis_monitor_disk_error": "Ne povis monitori diskojn: {error}",
"log_link_to_log": "Plena ŝtipo de ĉi tiu operacio: '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\"> {desc} </a>'",
"service_no_log": "Neniu registro por montri por servo '{service:s}'",
"global_settings_cant_serialize_settings": "Ne eblis serialigi datumojn pri agordoj, motivo: {reason:s}",
"backup_running_hooks": "Kurado de apogaj hokoj …",
"package_not_installed": "Pako '{pkgname}' ne estas instalita",
"certmanager_domain_unknown": "Nekonata domajno '{domain:s}'",
"unexpected_error": "Io neatendita iris malbone: {error}",
"password_listed": "Ĉi tiu pasvorto estas inter la plej uzataj pasvortoj en la mondo. Bonvolu elekti ion pli unikan.",
"ssowat_persistent_conf_write_error": "Ne povis konservi konstantan SSOwat-agordon: {error:s}. Redakti /etc/ssowat/conf.json.persistent dosiero por ripari la Jaks-sintakson",
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "Lasu la SSH-agordon estu administrata de YunoHost (paŝo 1, aŭtomata)",
"migration_0009_not_needed": "Ĉi tiu migrado jam iel okazis ... (?) Saltado.",
"ssowat_conf_generated": "SSOwat-agordo generita",
"migrate_tsig_wait": "Atendante tri minutojn por ke la servilo DynDNS enkalkulu la novan ŝlosilon …",
"log_remove_on_failed_restore": "Forigu '{}' post malsukcesa restarigo de rezerva ar archiveivo",
"dpkg_is_broken": "Vi ne povas fari ĉi tion nun ĉar dpkg/APT (la administrantoj pri pakaĵaj sistemoj) ŝajnas esti rompita stato ... Vi povas provi solvi ĉi tiun problemon per konekto per SSH kaj funkcianta `sudo dpkg --configure -a`.",
"recommend_to_add_first_user": "La postinstalo finiĝis, sed YunoHost bezonas almenaŭ unu uzanton por funkcii ĝuste, vi devas aldoni unu uzante 'yunohost user create <username>' aŭ fari ĝin de la administra interfaco.",
"certmanager_cert_signing_failed": "Ne povis subskribi la novan atestilon",
"migration_description_0003_migrate_to_stretch": "Altgradigu la sistemon al Debian Stretch kaj YunoHost 3.0",
"log_tools_upgrade": "Ĝisdatigu sistemajn pakaĵojn",
"network_check_smtp_ko": "Ekstera retpoŝto (SMTP-haveno 25) ŝajnas esti blokita de via reto",
"log_available_on_yunopaste": "Ĉi tiu protokolo nun haveblas per {url}",
"certmanager_http_check_timeout": "Ekdifinita kiam servilo provis kontakti sin per HTTP per publika IP-adreso (domajno '{domain:s}' kun IP '{ip:s}'). Vi eble spertas haŭtoproblemon, aŭ la fajroŝirmilo / enkursigilo antaŭ via servilo miskonfiguras.",
"pattern_port_or_range": "Devas esti valida haveno-nombro (t.e. 0-65535) aŭ gamo da havenoj (t.e. 100:200)",
"migrations_loading_migration": "Ŝarĝante migradon {id}…",
"port_available": "Haveno {port:d} estas havebla",
"pattern_mailbox_quota": "Devas esti grandeco kun la sufikso b/k/M/G/T aŭ 0 por ne havi kvoton",
"migration_0008_general_disclaimer": "Por plibonigi la sekurecon de via servilo, rekomendas lasi YunoHost administri la SSH-agordon. Via nuna SSH-aranĝo diferencas de la rekomendo. Se vi lasas YunoHost agordi ĝin, la maniero per kiu vi konektas al via servilo per SSH ŝanĝiĝos tiel:",
"user_deletion_failed": "Ne povis forigi uzanton {user}: {error}",
"backup_with_no_backup_script_for_app": "La app '{app:s}' ne havas sekretan skripton. Ignorante.",
"service_regen_conf_is_deprecated": "'yunohost service regen-conf' malakceptas! Bonvolu uzi anstataŭe 'yunohost tools regen-conf'.",
"global_settings_key_doesnt_exists": "La ŝlosilo '{settings_key:s}' ne ekzistas en la tutmondaj agordoj, vi povas vidi ĉiujn disponeblajn klavojn per uzado de 'yunohost settings list'",
"dyndns_no_domain_registered": "Neniu domajno registrita ĉe DynDNS",
"dyndns_could_not_check_available": "Ne povis kontroli ĉu {domain:s} haveblas sur {provider:s}.",
"log_app_removelist": "Forigu aplikan liston",
"global_settings_setting_example_enum": "Ekzemplo enum elekto",
"hook_exec_not_terminated": "Skripto ne finiĝis ĝuste: {path:s}",
"service_stopped": "'{service:s}' servo ĉesis",
"restore_failed": "Ne povis restarigi sistemon",
"confirm_app_install_danger": "Danĝero! Ĉi tiu apliko estas konata ankoraŭ eksperimenta (se ne eksplicite ne funkcias)! Vi probable ne devas instali ĝin krom se vi scias kion vi faras. NENIU SUBTENO estos provizita se ĉi tiu app ne funkcias aŭ rompas vian sistemon ... Se vi pretas riski ĉiuokaze, tajpu '{answers: s}'",
"log_operation_unit_unclosed_properly": "Operaciumo ne estis fermita ĝuste",
"upgrade_complete": "Ĝisdatigo kompleta",
"upnp_enabled": "UPnP ŝaltis",
"mailbox_used_space_dovecot_down": "La retpoŝta servo de Dovecot devas funkcii, se vi volas akcepti uzitan poŝtan spacon",
"restore_system_part_failed": "Ne povis restarigi la sisteman parton '{part:s}'",
"diagnosis_monitor_system_error": "Ne povis monitori sistemon: {error}",
"service_stop_failed": "Ne povis maldaŭrigi la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"unbackup_app": "App '{app:s}' ne konserviĝos",
"updating_apt_cache": "Akirante haveblajn ĝisdatigojn por sistemaj pakoj…",
"tools_upgrade_at_least_one": "Bonvolu specifi '--apps' aŭ '--system'",
"service_already_stopped": "La servo '{service:s}' jam ĉesis",
"unit_unknown": "Nekonata unuo '{unit:s}'",
"migration_0003_modified_files": "Bonvolu noti, ke la jenaj dosieroj estis trovitaj mane kaj modifitaj kaj povus esti anstataŭigitaj sekve de la ĝisdatigo: {manual_modified_files}",
"tools_upgrade_cant_both": "Ne eblas ĝisdatigi ambaŭ sistemon kaj programojn samtempe",
"restore_extracting": "Eltirante bezonatajn dosierojn el la ar theivo…",
"upnp_port_open_failed": "Ne povis malfermi havenon per UPnP",
"log_app_upgrade": "Ĝisdatigu la aplikon '{}'",
"log_help_to_get_failed_log": "La operacio '{desc}' ne povis finiĝi. Bonvolu dividi la plenan ŝtipon de ĉi tiu operacio per la komando 'yunohost log display {name} --share' por akiri helpon",
"migration_description_0002_migrate_to_tsig_sha256": "Plibonigu sekurecon de DynDNS TSIG-ĝisdatigoj per SHA-512 anstataŭ MD5",
"monitor_disabled": "Servila monitorado nun malŝaltis",
"pattern_port": "Devas esti valida havena numero (t.e. 0-65535)",
"port_already_closed": "Haveno {port:d} estas jam fermita por {ip_version:s} rilatoj",
"hook_name_unknown": "Nekonata hoko-nomo '{name:s}'",
"migration_0003_system_not_fully_up_to_date": "Via sistemo ne estas plene ĝisdata. Bonvolu plenumi regulan ĝisdatigon antaŭ ol ruli la migradon al Stretch.",
"dyndns_could_not_check_provide": "Ne povis kontroli ĉu {provider:s} povas provizi {domain:s}.",
"dyndns_cron_remove_failed": "Ne povis forigi la cron-laboron DynDNS ĉar: {error}",
"pattern_listname": "Devas esti nur alfanumeraj kaj substrekaj signoj",
"restore_nothings_done": "Nenio estis restarigita",
"log_tools_postinstall": "Afiŝu vian servilon YunoHost",
"dyndns_unavailable": "La domajno '{domain:s}' ne haveblas.",
"experimental_feature": "Averto: Ĉi tiu funkcio estas eksperimenta kaj ne konsiderata stabila, vi ne uzu ĝin krom se vi scias kion vi faras.",
"root_password_replaced_by_admin_password": "Via radika pasvorto estis anstataŭigita per via administra pasvorto.",
"ssowat_persistent_conf_read_error": "Ne povis legi konstantan SSOwat-agordon: {error:s}. Redakti /etc/ssowat/conf.json.persistent dosiero por ripari la Jaks-sintakson",
"migration_description_0005_postgresql_9p4_to_9p6": "Migru datumbazojn de PostgreSQL 9.4 al 9.6",
"migration_0008_root": "• Vi ne povos konekti kiel radiko per SSH. Anstataŭe vi uzu la administran uzanton;",
"package_unknown": "Nekonata pako '{pkgname}'",
"domain_unknown": "Nekonata domajno",
"global_settings_setting_security_password_user_strength": "Uzanto pasvorta forto",
"restore_may_be_not_enough_disk_space": "Via sistemo ŝajnas ne havi sufiĉe da spaco (free:{free_space:d} B, necesa spaco: {needed_space:d} B, sekureca marĝeno: {margin:d} B)",
"log_corrupted_md_file": "La YAD-metadata dosiero asociita kun protokoloj estas damaĝita: '{md_file}\nEraro: {error} '",
"downloading": "Elŝutante …",
"user_deleted": "Uzanto forigita",
"service_enable_failed": "Ne eblis ŝalti la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"tools_upgrade_special_packages": "Nun ĝisdatigi 'specialajn' (rilatajn al yunohost)…",
"domains_available": "Haveblaj domajnoj:",
"dyndns_registered": "Registrita domajno DynDNS",
"service_description_fail2ban": "Protektas kontraŭ bruta forto kaj aliaj specoj de atakoj de la interreto",
"file_does_not_exist": "La dosiero {path:s} ne ekzistas.",
"yunohost_not_installed": "YunoHost estas malĝuste aŭ ne ĝuste instalita. Bonvolu prilabori 'yunohost tools postinstall'",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 estas instalita, sed ne postgresql 9.6‽ Io stranga eble okazis en via sistemo: (…",
"restore_removing_tmp_dir_failed": "Ne povis forigi malnovan provizoran dosierujon",
"certmanager_cannot_read_cert": "Io malbona okazis, kiam mi provis malfermi aktualan atestilon por domajno {domain:s} (dosiero: {file:s}), kialo: {reason:s}",
"service_removed": "'{service:s}' servo forigita",
"certmanager_hit_rate_limit": "Tro multaj atestiloj jam eldonitaj por ĉi tiu ĝusta aro de domajnoj {domain:s} antaŭ nelonge. Bonvolu reprovi poste. Vidu https://letsencrypt.org/docs/rate-limits/ por pliaj detaloj",
"migration_0005_not_enough_space": "Disponigu sufiĉan spacon en {path} por ruli la migradon.",
"pattern_firstname": "Devas esti valida antaŭnomo",
"migration_description_0010_migrate_to_apps_json": "Forigu malvalorigitajn aparatojn kaj uzu anstataŭe la novan unuigitan liston \"apps.json\"",
"domain_cert_gen_failed": "Ne povis generi atestilon",
"regenconf_file_kept_back": "La agorda dosiero '{conf}' estas atendita forigi per regen-conf (kategorio {category}), sed ĝi estis konservita.",
"migrate_tsig_wait_4": "30 sekundoj …",
"backup_with_no_restore_script_for_app": "La apliko \"{app:s}\" ne havas restarigan skripton, vi ne povos aŭtomate restarigi la sekurkopion de ĉi tiu apliko.",
"log_letsencrypt_cert_install": "Instalu atestilon Let's Encrypt sur '{}' regado",
"log_dyndns_update": "Ĝisdatigu la IP asociita kun via subdominio YunoHost '{}'",
"firewall_reload_failed": "Ne eblis reŝargi la firewall",
"confirm_app_install_warning": "Averto: Ĉi tiu aplikaĵo povas funkcii, sed ne bone integras en YunoHost. Iuj funkcioj kiel ekzemple aliĝilo kaj sekurkopio / restarigo eble ne haveblos. Instali ĉiuokaze? [{answers: s}] ",
"log_user_delete": "Forigi uzanton '{}'",
"dyndns_ip_updated": "Ĝisdatigis vian IP sur DynDNS",
"regenconf_up_to_date": "La agordo jam estas ĝisdatigita por kategorio '{category}'",
"migration_0003_patching_sources_list": "Patching the sources.lists …",
"global_settings_setting_security_ssh_compatibility": "Kongruo vs sekureca kompromiso por la SSH-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"migrations_need_to_accept_disclaimer": "Por funkciigi la migradon {id}, via devas akcepti la sekvan malakcepton:\n---\n{malavantaĝo}\n---\nSe vi akceptas funkcii la migradon, bonvolu rekonduki la komandon kun la opcio '--accept-disclaimer'.",
"regenconf_file_remove_failed": "Ne povis forigi la agordodosieron '{conf}'",
"not_enough_disk_space": "Ne sufiĉe libera spaco sur '{path:s}'",
"migration_0006_disclaimer": "YunoHost nun atendas, ke la pasvortoj de admin kaj radiko estos sinkronigitaj. Ĉi tiu migrado anstataŭigas vian radikan pasvorton kun la administran pasvorton.",
"dyndns_ip_update_failed": "Ne povis ĝisdatigi IP-adreson al DynDNS",
"migration_description_0004_php5_to_php7_pools": "Rekonfigu la PHP-naĝejojn por uzi PHP 7 anstataŭ 5",
"monitor_glances_con_failed": "Ne povis konektiĝi al servilo de Glances",
"ssowat_conf_updated": "SSOwat-agordo ĝisdatigita",
"log_link_to_failed_log": "Ne povis plenumi la operacion '{desc}'. Bonvolu provizi la plenan protokolon de ĉi tiu operacio per <a href=\"#/tools/logs/{name}\"> alklakante ĉi tie </a> por akiri helpon",
"log_app_fetchlist": "Aldonu liston de aplikoj",
"user_home_creation_failed": "Ne povis krei dosierujon \"home\" por uzanto",
"pattern_backup_archive_name": "Devas esti valida dosiernomo kun maksimume 30 signoj, alfanombraj kaj -_. signoj nur",
"restore_cleaning_failed": "Ne eblis purigi la adresaron de provizora restarigo",
"dyndns_registration_failed": "Ne povis registri DynDNS-domajnon: {error:s}",
"migration_0003_not_jessie": "La nuna Debian-distribuo ne estas Jessie!",
"user_unknown": "Nekonata uzanto: {user:s}",
"migrations_to_be_ran_manually": "Migrado {id} devas funkcii permane. Bonvolu iri al Iloj → Migradoj en la retpaĝa paĝo, aŭ kuri `yunohost tools migrations migrate`.",
"migration_0008_warning": "Se vi komprenas tiujn avertojn kaj konsentas lasi YunoHost pretervidi vian nunan agordon, faru la migradon. Alie, vi ankaŭ povas salti la migradon - kvankam ĝi ne rekomendas.",
"certmanager_cert_renew_success": "Ni Ĉifru atestilon renovigitan por la domajno '{domain:s}'",
"global_settings_reset_success": "Antaŭaj agordoj nun estas rezervitaj al {path:s}",
"pattern_domain": "Devas esti valida domajna nomo (t.e. mia-domino.org)",
"package_unexpected_error": "Neatendita eraro okazis prilaborante la pakon '{pkgname}'",
"dyndns_key_generating": "Generi DNS-ŝlosilon ... Eble daŭros iom da tempo.",
"restore_running_app_script": "Restarigi la programon '{app:s}'…",
"migrations_skip_migration": "Salti migradon {id}…",
"mysql_db_init_failed": "MysQL-datumbazo init malsukcesis",
"regenconf_file_removed": "Agordodosiero '{conf}' forigita",
"log_tools_shutdown": "Enŝaltu vian servilon",
"password_too_simple_3": "La pasvorto bezonas almenaŭ 8 signojn kaj enhavas ciferon, majusklon, pli malaltan kaj specialajn signojn",
"migration_0003_general_warning": "Bonvolu noti, ke ĉi tiu migrado estas delikata operacio. La teamo de YunoHost faris sian plej bonan revizii kaj testi ĝin, sed la migrado eble ankoraŭ rompos partojn de la sistemo aŭ ĝiaj programoj.\n\nTial oni rekomendas al:\n - Elfari kopion de iuj kritikaj datumoj aŭ app. Pliaj informoj pri https://yunohost.org/backup;\n - Paciencu post lanĉo de la migrado: Depende de via interreta konekto kaj aparataro, eble daŭros kelkaj horoj ĝis ĉio ĝisdatigi.\n\nAldone, la haveno por SMTP, uzata de eksteraj retpoŝtaj klientoj (kiel Thunderbird aŭ K9-Mail) estis ŝanĝita de 465 (SSL / TLS) al 587 (STARTTLS). La malnova haveno (465) aŭtomate fermiĝos, kaj la nova haveno (587) malfermiĝos en la fajrejo. Vi kaj viaj uzantoj * devos adapti la agordon de viaj retpoŝtaj klientoj laŭe.",
"diagnosis_kernel_version_error": "Ne povis akiri la kernan version: {error}",
"global_settings_setting_example_int": "Ekzemple int elekto",
"backup_output_symlink_dir_broken": "Via arkiva dosierujo '{path:s}' estas rompita ligilo. Eble vi forgesis restarigi aŭ munti aŭ enŝovi la stokadon, al kiu ĝi notas.",
"good_practices_about_admin_password": "Vi nun estas por difini novan administran pasvorton. La pasvorto devas esti almenaŭ 8 signoj - kvankam estas bone praktiki uzi pli longan pasvorton (t.e. pasfrazon) kaj / aŭ uzi variaĵon de signoj (majuskloj, minuskloj, ciferoj kaj specialaj signoj).",
"certmanager_attempt_to_renew_valid_cert": "La atestilo por la domajno '{domain:s}' ne finiĝos! (Vi eble uzos --force se vi scias kion vi faras)",
"restore_running_hooks": "Kurantaj restarigaj hokoj…",
"regenconf_pending_applying": "Aplikante pritraktata agordo por kategorio '{category}'…",
"service_description_dovecot": "Permesas al retpoŝtaj klientoj aliri / serĉi retpoŝton (per IMAP kaj POP3)",
"domain_dns_conf_is_just_a_recommendation": "Ĉi tiu komando montras al vi la *rekomenditan* agordon. Ĝi efektive ne agordas la DNS-agordon por vi. Via respondeco agordi vian DNS-zonon en via registristo laŭ ĉi tiu rekomendo.",
"backup_php5_to_php7_migration_may_fail": "Ne povis konverti vian ar archiveivon por subteni PHP 7, vi eble ne povas restarigi viajn PHP-programojn (kialo: {error:s})",
"log_backup_restore_system": "Restarigi sistemon de rezerva arkivo",
"log_app_change_url": "Ŝanĝu la URL de la apliko '{}'",
"service_already_started": "La servo '{service:s}' estas jam komencita",
"license_undefined": "nedifinita",
"global_settings_setting_security_password_admin_strength": "Admin pasvorta forto",
"service_reload_or_restart_failed": "Ne povis reŝargi aŭ rekomenci la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"migrations_list_conflict_pending_done": "Vi ne povas uzi ambaŭ '--previous' kaj '--done' samtempe.",
"maindomain_changed": "La ĉefa domajno nun ŝanĝiĝis",
"server_shutdown_confirm": "La servilo haltos tuj, ĉu vi certas? [{answers:s}]",
"monitor_period_invalid": "Nevalida tempoperiodo",
"log_backup_restore_app": "Restarigu '{}' de rezerva ar archiveivo",
"log_does_exists": "Ne estas operacio-registro kun la nomo '{log}', uzu 'yunohost loglist' por vidi ĉiujn disponeblajn operaciojn",
"service_add_failed": "Ne povis aldoni la servon '{service:s}'",
"pattern_password_app": "Bedaŭrinde, pasvortoj ne povas enhavi jenajn signojn: {forbidden_chars}",
"this_action_broke_dpkg": "Ĉi tiu ago rompis dpkg / APT (la administrantoj pri la paka sistemo) ... Vi povas provi solvi ĉi tiun problemon per konekto per SSH kaj funkcianta `sudo dpkg --configure -a`.",
"log_regen_conf": "Regeneri sistemajn agordojn '{}'",
"restore_hook_unavailable": "La restariga skripto por '{part:s}' ne haveblas en via sistemo kaj ankaŭ ne en la ar theivo",
"network_check_smtp_ok": "Eksteren retpoŝto (SMTP-haveno 25) ne estas blokita",
"log_dyndns_subscribe": "Aboni al YunoHost-subdominio '{}'",
"password_too_simple_4": "La pasvorto bezonas almenaŭ 12 signojn kaj enhavas ciferon, majuskle, pli malaltan kaj specialajn signojn",
"migration_0003_main_upgrade": "Komencanta ĉefa ĝisdatigo …",
"user_info_failed": "Ne povis akiri informojn pri uzanto",
"regenconf_file_updated": "Agordodosiero '{conf}' ĝisdatigita",
"log_help_to_get_log": "Por vidi la protokolon de la operacio '{desc}', uzu la komandon 'yunohost log display {name}'",
"global_settings_setting_security_nginx_compatibility": "Kongruo vs sekureca kompromiso por la TTT-servilo NGINX. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
"no_internet_connection": "Servilo ne konektita al la interreto",
"migration_0008_dsa": "• La DSA-ŝlosilo estos malŝaltita. Tial vi eble bezonos nuligi spuran averton de via SSH-kliento kaj revizii la fingrospuron de via servilo;",
"migration_0003_restoring_origin_nginx_conf": "Fileia dosiero /etc/nginx/nginx.conf estis iel redaktita. La migrado reaperos unue al sia originala stato ... La antaŭa dosiero estos havebla kiel {backup_dest}.",
"migrate_tsig_end": "Migrado al HMAC-SHA-512 finiĝis",
"restore_complete": "Restarigita",
"certmanager_couldnt_fetch_intermediate_cert": "Ekvilibrigita kiam vi provis ricevi interajn atestilojn de Let's Encrypt. Atestita instalado / renovigo nuligita - bonvolu reprovi poste.",
"hook_exec_failed": "Ne povis funkcii skripto: {path:s}",
"global_settings_cant_open_settings": "Ne eblis malfermi agordojn, tial: {reason:s}",
"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 {domajno:s}! (Uzu --forte pretervidi)",
"monitor_stats_period_unavailable": "Ne ekzistas disponeblaj statistikoj por la periodo",
"regenconf_updated": "Agordo por kategorio '{category}' ĝisdatigita",
"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{sourcelist}",
"regenconf_dry_pending_applying": "Kontrolado de pritraktata agordo, kiu estus aplikita por kategorio '{category}'…",
"regenconf_file_copy_failed": "Ne povis kopii la novan agordodosieron '{new}' al '{conf}'",
"global_settings_setting_example_string": "Ekzemple korda elekto",
"restore_already_installed_app": "App kun la ID '{app:s}' estas jam instalita",
"mountpoint_unknown": "Nekonata montpunkto",
"log_tools_maindomain": "Faru de '{}' la ĉefa domajno",
"maindomain_change_failed": "Ne povis ŝanĝi la ĉefan domajnon",
"mail_domain_unknown": "Nevalida retadreso por domajno '{domain:s}'. Bonvolu uzi domajnon administritan de ĉi tiu servilo.",
"migrations_cant_reach_migration_file": "Ne povis aliri migrajn dosierojn ĉe la vojo% s",
"pattern_email": "Devas esti valida retpoŝtadreso (t.e.iu@domain.org)",
"mail_alias_remove_failed": "Ne povis forigi retpoŝton alias '{mail:s}'",
"regenconf_file_manually_removed": "La dosiero de agordo '{conf}' estis forigita permane, kaj ne estos kreita",
"monitor_enabled": "Servila monitorado nun ŝaltis",
"domain_exists": "La domajno jam ekzistas",
"migration_description_0001_change_cert_group_to_sslcert": "Ŝanĝu grupajn permesojn de 'metronomo' al 'ssl-cert'",
"mysql_db_creation_failed": "MySQL-datumbazkreado malsukcesis",
"ldap_initialized": "LDAP inicializis",
"migrate_tsig_not_needed": "Vi ne ŝajnas uzi DynDNS-domajnon, do neniu migrado necesas.",
"certmanager_domain_cert_not_selfsigned": "La atestilo por domajno {domajno:s} ne estas mem-subskribita. Ĉu vi certas, ke vi volas anstataŭigi ĝin? (Uzu '--force' por fari tion.)",
"certmanager_unable_to_parse_self_CA_name": "Ne povis trapasi nomon de mem-subskribinta aŭtoritato (dosiero: {file: s})",
"log_selfsigned_cert_install": "Instalu mem-subskribitan atestilon sur '{}' domajno",
"log_tools_reboot": "Reklamu vian servilon",
"certmanager_cert_install_success": "Ni Ĉifru atestilon nun instalitan por la domajno '{domain:s}'",
"global_settings_bad_choice_for_enum": "Malbona elekto por agordo {setting:s}, ricevita '{choice:s}', sed disponeblaj elektoj estas: {available_choices:s}",
"server_shutdown": "La servilo haltos",
"log_tools_migrations_migrate_forward": "Migri antaŭen",
"migration_0008_no_warning": "Neniu grava risko identigita pri superregado de via SSH-agordo, tamen oni ne povas esti absolute certa;)! Ekfunkciu la migradon por superregi ĝin. Alie, vi ankaŭ povas salti la migradon - kvankam ĝi ne rekomendas.",
"regenconf_now_managed_by_yunohost": "La agorda dosiero '{conf}' nun estas administrata de YunoHost (kategorio {category}).",
"server_reboot_confirm": "Ĉu la servilo rekomencos tuj, ĉu vi certas? [{answers:s}]",
"log_app_install": "Instalu la aplikon '{}'",
"service_description_dnsmasq": "Traktas rezolucion de domajna nomo (DNS)",
"global_settings_unknown_type": "Neatendita situacio, la agordo {setting:s} ŝajnas havi la tipon {unknown_type:s} sed ĝi ne estas tipo subtenata de la sistemo.",
"migration_0003_problematic_apps_warning": "Bonvolu noti, ke la sekvaj eventuale problemaj instalitaj apps estis detektitaj. Ĝi aspektas, ke tiuj ne estis instalitaj de aparato aŭ ne estas markitaj kiel \"funkciantaj\". Tial ne eblas garantii, ke ili ankoraŭ funkcios post la ĝisdatigo: {problematic_apps}",
"domain_hostname_failed": "Ne povis agordi novan gastigilon. Ĉi tio eble kaŭzos problemon poste (eble bone).",
"server_reboot": "La servilo rekomenciĝos",
"regenconf_failed": "Ne povis regeneri la agordon por kategorio(j): {categories}",
"domain_uninstall_app_first": "Unu aŭ pluraj programoj estas instalitaj en ĉi tiu domajno. Bonvolu malinstali ilin antaŭ ol daŭrigi la domajnan forigon",
"port_unavailable": "Haveno {port:d} ne haveblas",
"service_unknown": "Nekonata servo '{service:s}'",
"migration_0003_start": "Komencante migradon al Stretch. La protokoloj haveblos en {logfile}.",
"monitor_stats_no_update": "Neniuj monitoradaj statistikoj ĝisdatigi",
"domain_deletion_failed": "Ne povis forigi domajnon {domain}: {error}",
"log_user_update": "Ĝisdatigu uzantinformojn de '{}'",
"user_creation_failed": "Ne povis krei uzanton {user}: {error}",
"migrations_migration_has_failed": "Migrado {id} ne kompletigis, abolis. Eraro: {exception}",
"done": "Farita",
"log_domain_remove": "Forigi domon '{}' de agordo de sistemo",
"monitor_not_enabled": "Servila monitorado estas malŝaltita",
"diagnosis_debian_version_error": "Ne povis retrovi la Debianan version: {error}",
"hook_list_by_invalid": "Ĉi tiu posedaĵo ne povas esti uzata por listigi hokojn",
"confirm_app_install_thirdparty": "Danĝero! Ĉi tiu apliko ne estas parto de la aplika katalogo de Yunohost. Instali triajn aplikojn povas kompromiti la integrecon kaj sekurecon de via sistemo. Vi probable ne devas instali ĝin krom se vi scias kion vi faras. NENIU SUBTENO estos provizita se ĉi tiu app ne funkcias aŭ rompas vian sistemon ... Se vi pretas riski ĉiuokaze, tajpu '{answers: s}'",
"global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Permesu uzon de (malaktuala) DSA-hostkey por la agordo de daemon SSH",
"dyndns_domain_not_provided": "Provizanto DynDNS {provider:s} ne povas provizi domajnon {domain:s}.",
"backup_unable_to_organize_files": "Ne povis uzi la rapidan metodon por organizi dosierojn en la ar archiveivo",
"password_too_simple_2": "La pasvorto bezonas almenaŭ 8 signojn kaj enhavas ciferon, majusklojn kaj minusklojn",
"executing_script": "Plenumanta skripto '{script:s}' …",
"service_cmd_exec_failed": "Ne povis plenumi la komandon '{command:s}'",
"migration_0007_cancelled": "Ne povis plibonigi la manieron kiel via SSH-agordo estas administrita.",
"migrate_tsig_failed": "Ne povis migri la DynDNS-domajnon '{domain}' al HMAC-SHA-512, ruliĝante. Eraro: {error_code}, {error}",
"pattern_lastname": "Devas esti valida familinomo",
"service_enabled": "'{service:s}' servo malŝaltita",
"certmanager_no_cert_file": "Ne povis legi la atestan dosieron por la domajno {domain:s} (dosiero: {file:s})",
"migration_0008_port": "• Vi devos konekti uzante la havenon 22 anstataŭ via nuna kutimo SSH-haveno. Sentu vin libera reconfiguri ĝin;",
"domain_creation_failed": "Ne povis krei domajnon {domain}: {error}",
"certmanager_domain_http_not_working": "Ŝajnas ke la domajno {domain:s} ne atingeblas per HTTP. Kontrolu, ke via DNS kaj NGINX-agordo ĝustas",
"domain_cannot_remove_main": "Ne eblas forigi ĉefan domajnon. Fiksu unu unue",
"service_reloaded_or_restarted": "'{service:s}' servo reŝarĝis aŭ rekomencis",
"mysql_db_initialized": "La datumbazo MySQL jam estas pravalorizita",
"log_domain_add": "Aldonu '{}' domajnon en sisteman agordon",
"global_settings_bad_type_for_setting": "Malbona tipo por agordo {setting:s}, ricevita {received_type:s}, atendata {expected_type:s}",
"unlimit": "Neniu kvoto",
"dyndns_cron_installed": "Kreita laboro DynDNS cron",
"system_username_exists": "Uzantnomo jam ekzistas en la listo de uzantoj de sistemo",
"firewall_reloaded": "Fajroŝirmilo reŝarĝis",
"service_restarted": "'{service:s}' servo rekomencis",
"pattern_username": "Devas esti minuskulaj literoj kaj minuskloj nur",
"extracting": "Eltirante…",
"restore_app_failed": "Ne povis restarigi la programon '{app:s}'",
"yunohost_configured": "YunoHost nun agordis",
"certmanager_self_ca_conf_file_not_found": "Ne povis trovi agorddosieron por mem-subskriba aŭtoritato (dosiero: {file:s})",
"log_app_remove": "Forigu la aplikon '{}'",
"service_restart_failed": "Ne povis rekomenci la servon '{service:s}'\n\nLastatempaj servaj protokoloj: {logs:s}",
"firewall_rules_cmd_failed": "Iuj komandoj pri fajroŝirmilo malsukcesis. Pliaj informoj en ensaluto.",
"certmanager_certificate_fetching_or_enabling_failed": "Provante uzi la novan atestilon por {domain:s} ne funkciis …",
"app_full_domain_unavailable": "Bedaŭrinde, ĉi tiu app devas esti instalita sur propra domajno, sed aliaj programoj jam estas instalitaj sur la domajno '{domain}'. Vi povus uzi subdominon dediĉitan al ĉi tiu app anstataŭe.",
"migration_0011_slapd_config_will_be_overwritten": "Ŝajnas ke vi permane redaktis la slapd-agordon. Por ĉi tiu kritika migrado, YunoHost bezonas devigi la ĝisdatigon de la slapd-agordo. La originalaj dosieroj estos rezervitaj en {conf_backup_folder}.",
"group_cannot_edit_all_users": "La grupo 'all_users' ne povas esti redaktita permane. Ĝi estas speciala grupo celita enhavi ĉiujn uzantojn registritajn en YunoHost",
"group_cannot_edit_visitors": "La grupo 'vizitantoj' ne povas esti redaktita permane. Ĝi estas speciala grupo reprezentanta anonimajn vizitantojn",
"group_cannot_edit_primary_group": "La grupo '{group}' ne povas esti redaktita permane. Ĝi estas la primara grupo celita enhavi nur unu specifan uzanton.",
"log_permission_url": "Ĝisdatigu url-rilataj al permeso '{}'",
"permission_already_up_to_date": "La permeso ne estis ĝisdatigita ĉar la petoj pri aldono/forigo jam kongruas kun la aktuala stato.",
"permission_currently_allowed_for_visitors": "Ĉi tiu permeso estas nuntempe donita al vizitantoj aldone al aliaj grupoj. Vi probable volas aŭ forigi la permeson de \"vizitantoj\" aŭ forigi la aliajn grupojn al kiuj ĝi nun estas koncedita.",
"permission_currently_allowed_for_all_users": "Ĉi tiu permeso estas nuntempe donita al ĉiuj uzantoj aldone al aliaj grupoj. Vi probable volas aŭ forigi la permeson \"all_users\" aŭ forigi la aliajn grupojn, kiujn ĝi nuntempe donas.",
"app_install_failed": "Ne povis instali {app} : {error}",
"app_install_script_failed": "Eraro okazis en la skripto de instalado de la app"
} }

View file

@ -29,10 +29,10 @@
"app_unsupported_remote_type": "Tipo remoto no soportado por la aplicación", "app_unsupported_remote_type": "Tipo remoto no soportado por la aplicación",
"app_upgrade_failed": "No se pudo actualizar {app:s}", "app_upgrade_failed": "No se pudo actualizar {app:s}",
"app_upgraded": "Actualizado {app:s}", "app_upgraded": "Actualizado {app:s}",
"appslist_fetched": "Obtenida lista de aplicaciones {appslist:s} actualizada", "appslist_fetched": "Lista de aplicaciones «{appslist:s}» actualizada",
"appslist_removed": "Eliminada la lista de aplicaciones {appslist:s}", "appslist_removed": "Eliminada la lista de aplicaciones «{appslist:s}»",
"appslist_retrieve_error": "No se puede recuperar la lista remota de aplicaciones {appslist:s}: {error:s}", "appslist_retrieve_error": "No se puede recuperar la lista remota de aplicaciones «{appslist:s}»: {error:s}",
"appslist_unknown": "Lista de aplicaciones {appslist:s} desconocida.", "appslist_unknown": "Lista de aplicaciones «{appslist:s}» desconocida.",
"ask_current_admin_password": "Contraseña administrativa actual", "ask_current_admin_password": "Contraseña administrativa actual",
"ask_email": "Dirección de correo electrónico", "ask_email": "Dirección de correo electrónico",
"ask_firstname": "Nombre", "ask_firstname": "Nombre",
@ -70,13 +70,13 @@
"diagnosis_monitor_disk_error": "No se pudieron monitorizar los discos: {error}", "diagnosis_monitor_disk_error": "No se pudieron monitorizar los discos: {error}",
"diagnosis_monitor_network_error": "No se pudo monitorizar la red: {error}", "diagnosis_monitor_network_error": "No se pudo monitorizar la red: {error}",
"diagnosis_monitor_system_error": "No se pudo monitorizar el sistema: {error}", "diagnosis_monitor_system_error": "No se pudo monitorizar el sistema: {error}",
"diagnosis_no_apps": "Aplicación no instalada", "diagnosis_no_apps": "No hay tal aplicación instalada",
"dnsmasq_isnt_installed": "Parece que dnsmasq no está instalado, ejecute «apt-get remove bind9 && apt-get install it»", "dnsmasq_isnt_installed": "Parece que dnsmasq no está instalado, ejecute «apt-get remove bind9 && apt-get install it»",
"domain_cert_gen_failed": "No se pudo generar el certificado", "domain_cert_gen_failed": "No se pudo generar el certificado",
"domain_created": "Dominio creado", "domain_created": "Dominio creado",
"domain_creation_failed": "No se pudo crear el dominio", "domain_creation_failed": "No se pudo crear el dominio {domain}: {error}",
"domain_deleted": "Dominio eliminado", "domain_deleted": "Dominio eliminado",
"domain_deletion_failed": "No se pudo eliminar el dominio", "domain_deletion_failed": "No se pudo eliminar el dominio {domain}: {error}",
"domain_dyndns_already_subscribed": "Ya se ha suscrito a un dominio de DynDNS", "domain_dyndns_already_subscribed": "Ya se ha suscrito a un dominio de DynDNS",
"domain_dyndns_invalid": "Este dominio no se puede usar con DynDNS", "domain_dyndns_invalid": "Este dominio no se puede usar con DynDNS",
"domain_dyndns_root_unknown": "Dominio raíz de DynDNS desconocido", "domain_dyndns_root_unknown": "Dominio raíz de DynDNS desconocido",
@ -119,12 +119,12 @@
"ldap_initialized": "Inicializado LDAP", "ldap_initialized": "Inicializado LDAP",
"license_undefined": "indefinido", "license_undefined": "indefinido",
"mail_alias_remove_failed": "No se pudo eliminar el alias de correo «{mail:s}»", "mail_alias_remove_failed": "No se pudo eliminar el alias de correo «{mail:s}»",
"mail_domain_unknown": "Dirección de correo desconocida para el dominio «{domain:s}»", "mail_domain_unknown": "Dirección de correo no válida para el dominio «{domain:s}». Use un dominio administrado por este servidor.",
"mail_forward_remove_failed": "No se pudo eliminar el reenvío de correo «{mail:s}»", "mail_forward_remove_failed": "No se pudo eliminar el reenvío de correo «{mail:s}»",
"main_domain_change_failed": "No se pudo cambiar el dominio principal", "main_domain_change_failed": "No se pudo cambiar el dominio principal",
"main_domain_changed": "El dominio principal ha cambiado", "main_domain_changed": "El dominio principal ha cambiado",
"monitor_disabled": "Desactivada la monitorización del servidor", "monitor_disabled": "La monitorización del servidor está ahora desactivada",
"monitor_enabled": "Activada la monitorización del servidor", "monitor_enabled": "La monitorización del servidor está ahora activada",
"monitor_glances_con_failed": "No se pudo conectar al servidor de Glances", "monitor_glances_con_failed": "No se pudo conectar al servidor de Glances",
"monitor_not_enabled": "La monitorización del servidor está apagada", "monitor_not_enabled": "La monitorización del servidor está apagada",
"monitor_period_invalid": "Período de tiempo no válido", "monitor_period_invalid": "Período de tiempo no válido",
@ -132,9 +132,9 @@
"monitor_stats_no_update": "No hay estadísticas de monitorización para actualizar", "monitor_stats_no_update": "No hay estadísticas de monitorización para actualizar",
"monitor_stats_period_unavailable": "No hay estadísticas para el período", "monitor_stats_period_unavailable": "No hay estadísticas para el período",
"mountpoint_unknown": "Punto de montaje desconocido", "mountpoint_unknown": "Punto de montaje desconocido",
"mysql_db_creation_failed": "Error al crear la base de datos de MySQL", "mysql_db_creation_failed": "No se pudo crear la base de datos MySQL",
"mysql_db_init_failed": "Error al iniciar la base de datos de MySQL", "mysql_db_init_failed": "No se pudo inicializar la base de datos MySQL",
"mysql_db_initialized": "Inicializada la base de datos MySQL", "mysql_db_initialized": "La base de datos MySQL está ahora inicializada",
"network_check_mx_ko": "El registro DNS MX no está configurado", "network_check_mx_ko": "El registro DNS MX no está configurado",
"network_check_smtp_ko": "El correo saliente (SMTP puerto 25) parece estar bloqueado por su red", "network_check_smtp_ko": "El correo saliente (SMTP puerto 25) parece estar bloqueado por su red",
"network_check_smtp_ok": "El correo saliente (SMTP puerto 25) no está bloqueado", "network_check_smtp_ok": "El correo saliente (SMTP puerto 25) no está bloqueado",
@ -144,7 +144,7 @@
"no_ipv6_connectivity": "La conexión por IPv6 no está disponible", "no_ipv6_connectivity": "La conexión por IPv6 no está disponible",
"no_restore_script": "No se ha encontrado un script de restauración para la aplicación '{app:s}'", "no_restore_script": "No se ha encontrado un script de restauración para la aplicación '{app:s}'",
"not_enough_disk_space": "No hay espacio libre suficiente en «{path:s}»", "not_enough_disk_space": "No hay espacio libre suficiente en «{path:s}»",
"package_not_installed": "El paquete '{pkgname}' no está instalado", "package_not_installed": "El paquete «{pkgname}» no está instalado",
"package_unexpected_error": "Ha ocurrido un error inesperado procesando el paquete '{pkgname}'", "package_unexpected_error": "Ha ocurrido un error inesperado procesando el paquete '{pkgname}'",
"package_unknown": "Paquete desconocido '{pkgname}'", "package_unknown": "Paquete desconocido '{pkgname}'",
"packages_no_upgrade": "No hay paquetes para actualizar", "packages_no_upgrade": "No hay paquetes para actualizar",
@ -153,7 +153,7 @@
"path_removal_failed": "No se pudo eliminar la ruta {:s}", "path_removal_failed": "No se pudo eliminar la ruta {:s}",
"pattern_backup_archive_name": "Debe ser un nombre de archivo válido con un máximo de 30 caracteres, solo se admiten caracteres alfanuméricos y los caracteres -_. (guiones y punto)", "pattern_backup_archive_name": "Debe ser un nombre de archivo válido con un máximo de 30 caracteres, solo se admiten caracteres alfanuméricos y los caracteres -_. (guiones y punto)",
"pattern_domain": "El nombre de dominio debe ser válido (por ejemplo mi-dominio.org)", "pattern_domain": "El nombre de dominio debe ser válido (por ejemplo mi-dominio.org)",
"pattern_email": "Debe ser una dirección de correo electrónico válida (por ejemplo, alguien@dominio.org)", "pattern_email": "Debe ser una dirección de correo electrónico válida (p.ej. alguien@example.com)",
"pattern_firstname": "Debe ser un nombre válido", "pattern_firstname": "Debe ser un nombre válido",
"pattern_lastname": "Debe ser un apellido válido", "pattern_lastname": "Debe ser un apellido válido",
"pattern_listname": "Solo se pueden usar caracteres alfanuméricos y el guion bajo", "pattern_listname": "Solo se pueden usar caracteres alfanuméricos y el guion bajo",
@ -180,7 +180,7 @@
"restore_running_hooks": "Ejecutando los ganchos de restauración…", "restore_running_hooks": "Ejecutando los ganchos de restauración…",
"service_add_failed": "No se pudo añadir el servicio «{service:s}»", "service_add_failed": "No se pudo añadir el servicio «{service:s}»",
"service_added": "Añadido el servicio «{service:s}»", "service_added": "Añadido el servicio «{service:s}»",
"service_already_started": "El servicio «{service:s}» ya ha sido iniciado", "service_already_started": "El servicio «{service:s}» ya está funcionando",
"service_already_stopped": "El servicio «{service:s}» ya ha sido detenido", "service_already_stopped": "El servicio «{service:s}» ya ha sido detenido",
"service_cmd_exec_failed": "No se pudo ejecutar la orden «{command:s}»", "service_cmd_exec_failed": "No se pudo ejecutar la orden «{command:s}»",
"service_conf_file_backed_up": "Se ha realizado una copia de seguridad del archivo de configuración '{conf}' en '{backup}'", "service_conf_file_backed_up": "Se ha realizado una copia de seguridad del archivo de configuración '{conf}' en '{backup}'",
@ -195,10 +195,10 @@
"service_conf_updated": "La configuración ha sido actualizada para el servicio '{service}'", "service_conf_updated": "La configuración ha sido actualizada para el servicio '{service}'",
"service_conf_would_be_updated": "La configuración podría haber sido actualizada para el servicio '{service} 1'", "service_conf_would_be_updated": "La configuración podría haber sido actualizada para el servicio '{service} 1'",
"service_disable_failed": "No se pudo desactivar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}", "service_disable_failed": "No se pudo desactivar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_disabled": "Desactivado el servicio «{service:s}»", "service_disabled": "El servicio «{service:s}» ha sido desactivado",
"service_enable_failed": "No se pudo activar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}", "service_enable_failed": "No se pudo activar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_enabled": "Activado el servicio «{service:s}»", "service_enabled": "El servicio «{service:s}» ha sido desactivado",
"service_no_log": "No hay ningún registro para el servicio '{service:s}'", "service_no_log": "No hay ningún registro que mostrar para el servicio «{service:s}»",
"service_regenconf_dry_pending_applying": "Comprobando configuración pendiente que podría haber sido aplicada al servicio '{service}'...", "service_regenconf_dry_pending_applying": "Comprobando configuración pendiente que podría haber sido aplicada al servicio '{service}'...",
"service_regenconf_failed": "No se puede regenerar la configuración para el servicio(s): {services}", "service_regenconf_failed": "No se puede regenerar la configuración para el servicio(s): {services}",
"service_regenconf_pending_applying": "Aplicando la configuración pendiente para el servicio '{service}'...", "service_regenconf_pending_applying": "Aplicando la configuración pendiente para el servicio '{service}'...",
@ -208,7 +208,7 @@
"service_started": "Iniciado el servicio «{service:s}»", "service_started": "Iniciado el servicio «{service:s}»",
"service_status_failed": "No se pudo determinar el estado del servicio «{service:s}»", "service_status_failed": "No se pudo determinar el estado del servicio «{service:s}»",
"service_stop_failed": "No se pudo detener el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}", "service_stop_failed": "No se pudo detener el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_stopped": "Detenido el servicio «{service:s}»", "service_stopped": "El servicio «{service:s}» se detuvo",
"service_unknown": "Servicio desconocido '{service:s}'", "service_unknown": "Servicio desconocido '{service:s}'",
"ssowat_conf_generated": "Generada la configuración de SSOwat", "ssowat_conf_generated": "Generada la configuración de SSOwat",
"ssowat_conf_updated": "Actualizada la configuración de SSOwat", "ssowat_conf_updated": "Actualizada la configuración de SSOwat",
@ -228,17 +228,17 @@
"upnp_enabled": "UPnP activado", "upnp_enabled": "UPnP activado",
"upnp_port_open_failed": "No se pudo abrir el puerto vía UPnP", "upnp_port_open_failed": "No se pudo abrir el puerto vía UPnP",
"user_created": "Usuario creado", "user_created": "Usuario creado",
"user_creation_failed": "No se pudo crear el usuario", "user_creation_failed": "No se pudo crear el usuario {user}: {error}",
"user_deleted": "Usuario eliminado", "user_deleted": "Usuario eliminado",
"user_deletion_failed": "No se pudo eliminar el usuario", "user_deletion_failed": "No se pudo eliminar el usuario {user}: {error}",
"user_home_creation_failed": "No se pudo crear la carpeta «home» para el usuario", "user_home_creation_failed": "No se pudo crear la carpeta «home» para el usuario",
"user_info_failed": "No se pudo obtener la información del usuario", "user_info_failed": "No se pudo obtener la información del usuario",
"user_unknown": "Usuario desconocido: {user:s}", "user_unknown": "Usuario desconocido: {user:s}",
"user_update_failed": "No se pudo cambiar la información del usuario", "user_update_failed": "No se pudo actualizar el usuario {user}: {error}",
"user_updated": "Cambiada la información de usuario", "user_updated": "Cambiada la información de usuario",
"yunohost_already_installed": "YunoHost ya está instalado", "yunohost_already_installed": "YunoHost ya está instalado",
"yunohost_ca_creation_failed": "No se pudo crear la autoridad de certificación", "yunohost_ca_creation_failed": "No se pudo crear la autoridad de certificación",
"yunohost_configured": "YunoHost está configurado", "yunohost_configured": "YunoHost está ahora configurado",
"yunohost_installing": "Instalando YunoHost…", "yunohost_installing": "Instalando YunoHost…",
"yunohost_not_installed": "YunoHost no está correctamente instalado. Ejecute «yunohost tools postinstall»", "yunohost_not_installed": "YunoHost no está correctamente instalado. Ejecute «yunohost tools postinstall»",
"ldap_init_failed_to_create_admin": "La inicialización de LDAP no pudo crear el usuario «admin»", "ldap_init_failed_to_create_admin": "La inicialización de LDAP no pudo crear el usuario «admin»",
@ -272,25 +272,25 @@
"certmanager_acme_not_configured_for_domain": "El certificado para el dominio «{domain:s}» no parece que esté instalado correctamente. Ejecute primero «cert-install» para este dominio.", "certmanager_acme_not_configured_for_domain": "El certificado para el dominio «{domain:s}» no parece que esté instalado correctamente. Ejecute primero «cert-install» para este dominio.",
"certmanager_http_check_timeout": "Tiempo de espera agotado cuando el servidor intentaba conectarse consigo mismo a través de HTTP usando una dirección IP pública (dominio «{domain:s}» con IP «{ip:s}»). Puede que esté experimentando un problema de redirección («hairpinning»), o que el cortafuegos o el enrutador de su servidor esté mal configurado.", "certmanager_http_check_timeout": "Tiempo de espera agotado cuando el servidor intentaba conectarse consigo mismo a través de HTTP usando una dirección IP pública (dominio «{domain:s}» con IP «{ip:s}»). Puede que esté experimentando un problema de redirección («hairpinning»), o que el cortafuegos o el enrutador de su servidor esté mal configurado.",
"certmanager_couldnt_fetch_intermediate_cert": "Tiempo de espera agotado intentando obtener el certificado intermedio de Let's Encrypt. Cancelada la instalación o renovación del certificado. Vuelva a intentarlo más tarde.", "certmanager_couldnt_fetch_intermediate_cert": "Tiempo de espera agotado intentando obtener el certificado intermedio de Let's Encrypt. Cancelada la instalación o renovación del certificado. Vuelva a intentarlo más tarde.",
"appslist_retrieve_bad_format": "No se pudo leer la lista de aplicaciones obtenida {appslist:s}", "appslist_retrieve_bad_format": "No se pudo leer la lista de aplicaciones obtenida «{appslist:s}»",
"domain_hostname_failed": "No se pudo establecer un nuevo nombre de anfitrión («hostname»). Esto podría causar problemas más tarde (no es seguro... podría ir bien).", "domain_hostname_failed": "No se pudo establecer un nuevo nombre de anfitrión («hostname»). Esto podría causar problemas más tarde (no es seguro... podría ir bien).",
"yunohost_ca_creation_success": "Creada la autoridad de certificación local.", "yunohost_ca_creation_success": "Creada la autoridad de certificación local.",
"app_already_installed_cant_change_url": "Esta aplicación ya está instalada. No se puede cambiar el URL únicamente mediante esta función. Compruebe si está disponible la opción `app changeurl`.", "app_already_installed_cant_change_url": "Esta aplicación ya está instalada. No se puede cambiar el URL únicamente mediante esta función. Compruebe si está disponible la opción `app changeurl`.",
"app_change_no_change_url_script": "La aplicacion {app_name:s} aún no permite cambiar su URL, es posible que deba actualizarla.", "app_change_no_change_url_script": "La aplicacion {app_name:s} aún no permite cambiar su URL, es posible que deba actualizarla.",
"app_change_url_failed_nginx_reload": "No se pudo recargar NGINX. Esta es la salida de «nginx -t»:\n{nginx_errors:s}", "app_change_url_failed_nginx_reload": "No se pudo recargar NGINX. Esta es la salida de «nginx -t»:\n{nginx_errors:s}",
"app_change_url_identical_domains": "El antiguo y nuevo dominio/url_path son idénticos ('{domain:s} {path:s}'), no se realizarán cambios.", "app_change_url_identical_domains": "El antiguo y nuevo dominio/url_path son idénticos ('{domain:s} {path:s}'), no se realizarán cambios.",
"app_change_url_no_script": "Esta aplicación «{app_name:s}» aún no permite la modificación de URLs. Quizás debería actualizarla.", "app_change_url_no_script": "La aplicación «{app_name:s}» aún no permite la modificación de URLs. Quizás debería actualizarla.",
"app_change_url_success": "El URL de la aplicación {app:s} es ahora {domain:s} {path:s}", "app_change_url_success": "El URL de la aplicación {app:s} es ahora {domain:s} {path:s}",
"app_location_unavailable": "Este URL o no está disponible o está en conflicto con otra(s) aplicación(es) instalada(s):\n{apps:s}", "app_location_unavailable": "Este URL o no está disponible o está en conflicto con otra(s) aplicación(es) instalada(s):\n{apps:s}",
"app_already_up_to_date": "La aplicación {app:s} ya está actualizada", "app_already_up_to_date": "La aplicación {app:s} ya está actualizada",
"appslist_name_already_tracked": "Ya existe una lista de aplicaciones registradas con el nombre {name:s}.", "appslist_name_already_tracked": "Ya existe una lista de aplicaciones registradas con el nombre {name:s}.",
"appslist_url_already_tracked": "Ya existe una lista de aplicaciones registradas con el URL {url:s}.", "appslist_url_already_tracked": "Ya existe una lista de aplicaciones registradas con el URL {url:s}.",
"appslist_migrating": "Migrando la lista de aplicaciones {appslist:s}…", "appslist_migrating": "Migrando la lista de aplicaciones «{appslist:s}»…",
"appslist_could_not_migrate": "¡No se pudo migrar la lista de aplicaciones {appslist:s}! No se pudo analizar el URL… El antiguo trabajo de cron se mantuvo en {bkp_file:s}.", "appslist_could_not_migrate": "¡No se pudo migrar la lista de aplicaciones «{appslist:s}»! No se pudo analizar el URL… El antiguo trabajo de cron se mantuvo en {bkp_file:s}.",
"appslist_corrupted_json": "No se pudieron cargar las listas de aplicaciones. Parece que {filename:s} está dañado.", "appslist_corrupted_json": "No se pudieron cargar las listas de aplicaciones. Parece que {filename:s} está dañado.",
"invalid_url_format": "Algo va mal con el URL", "invalid_url_format": "Algo va mal con el URL",
"app_upgrade_some_app_failed": "No se pudieron actualizar algunas aplicaciones", "app_upgrade_some_app_failed": "No se pudieron actualizar algunas aplicaciones",
"app_make_default_location_already_used": "No puede hacer que la aplicación «{app}» sea la predeterminada en el dominio, {domain} ya está siendo usado por otra aplicación «{other_app}»", "app_make_default_location_already_used": "No puede hacer que la aplicación «{app}» sea la predeterminada en el dominio, «{domain}» ya está siendo usado por otra aplicación «{other_app}»",
"app_upgrade_app_name": "Actualizando ahora {app}…", "app_upgrade_app_name": "Actualizando ahora {app}…",
"ask_path": "Camino", "ask_path": "Camino",
"backup_abstract_method": "Este método de respaldo aún no se ha implementado", "backup_abstract_method": "Este método de respaldo aún no se ha implementado",
@ -301,7 +301,7 @@
"backup_archive_mount_failed": "No se pudo montar el archivo de respaldo", "backup_archive_mount_failed": "No se pudo montar el archivo de respaldo",
"backup_archive_system_part_not_available": "La parte del sistema «{part:s}» no está disponible en esta copia de seguridad", "backup_archive_system_part_not_available": "La parte del sistema «{part:s}» no está disponible en esta copia de seguridad",
"backup_archive_writing_error": "No se pudieron añadir los archivos «{source:s}» (llamados en el archivo «{dest:s}») para ser respaldados en el archivo comprimido «{archive:s}»", "backup_archive_writing_error": "No se pudieron añadir los archivos «{source:s}» (llamados en el archivo «{dest:s}») para ser respaldados en el archivo comprimido «{archive:s}»",
"backup_ask_for_copying_if_needed": "No se pudieron preparar algunos archivos para la copia de seguridad usando el método que evita desperdiciar espacio temporalmente en el sistema. Para hacer la copia de seguridad, {size:s}MB se usarán temporalmente. ¿Está de acuerdo?", "backup_ask_for_copying_if_needed": "¿Quiere realizar la copia de seguridad usando {size:s} MB temporalmente? (Se usa este modo ya que algunos archivos no se pudieron preparar usando un método más eficiente.)",
"backup_borg_not_implemented": "El método de respaldo de Borg aún no ha sido implementado", "backup_borg_not_implemented": "El método de respaldo de Borg aún no ha sido implementado",
"backup_cant_mount_uncompress_archive": "No se pudo montar el archivo descomprimido como protegido contra escritura", "backup_cant_mount_uncompress_archive": "No se pudo montar el archivo descomprimido como protegido contra escritura",
"backup_copying_to_organize_the_archive": "Copiando {size:s}MB para organizar el archivo", "backup_copying_to_organize_the_archive": "Copiando {size:s}MB para organizar el archivo",
@ -331,22 +331,22 @@
"update_apt_cache_warning": "Algo fue mal durante la actualización de la caché de APT (gestor de paquetes de Debian). Aquí tiene un volcado de las líneas de sources.list que podría ayudarle a identificar las líneas problemáticas:\n{sourceslist}", "update_apt_cache_warning": "Algo fue mal durante la actualización de la caché de APT (gestor de paquetes de Debian). Aquí tiene un volcado de las líneas de sources.list que podría ayudarle a identificar las líneas problemáticas:\n{sourceslist}",
"update_apt_cache_failed": "No se pudo actualizar la caché de APT (gestor de paquetes de Debian). Aquí tiene un volcado de las líneas de sources.list que podría ayudarle a identificar las líneas problemáticas:\n{sourceslist}", "update_apt_cache_failed": "No se pudo actualizar la caché de APT (gestor de paquetes de Debian). Aquí tiene un volcado de las líneas de sources.list que podría ayudarle a identificar las líneas problemáticas:\n{sourceslist}",
"tools_upgrade_special_packages_completed": "Actualización de paquetes de YunoHost completada.\nPulse [Intro] para regresar a la línea de órdenes", "tools_upgrade_special_packages_completed": "Actualización de paquetes de YunoHost completada.\nPulse [Intro] para regresar a la línea de órdenes",
"tools_upgrade_special_packages_explanation": "Esta acción terminará pero la actualización especial real continuará en segundo plano. No inicie ninguna otra acción en su servidor en aproximadamente 10 minutos (dependiendo de la velocidad de su hardware). Una vez que esté hecho, podría tener que volver a iniciar sesión en la administración web. El registro de actualización estará disponible en Herramientas → Registro (en la página de administración web) o mediante «yunohost log list» (desde la línea de órdenes).", "tools_upgrade_special_packages_explanation": "Esta acción terminará pero la actualización especial real continuará en segundo plano. No inicie ninguna otra acción en su servidor en aproximadamente 10 minutos (dependiendo de la velocidad de su hardware). Una vez hecho, podría tener que volver a iniciar sesión en la administración web. El registro de actualización estará disponible en Herramientas → Registro (en la página de administración web) o mediante «yunohost log list» (desde la línea de órdenes).",
"tools_upgrade_special_packages": "Actualizando ahora paquetes «especiales» (relacionados con YunoHost)…", "tools_upgrade_special_packages": "Actualizando ahora paquetes «especiales» (relacionados con YunoHost)…",
"tools_upgrade_regular_packages_failed": "No se pudieron actualizar los paquetes: {packages_list}", "tools_upgrade_regular_packages_failed": "No se pudieron actualizar los paquetes: {packages_list}",
"tools_upgrade_regular_packages": "Actualizando ahora paquetes «normales» (no relacionados con YunoHost)…", "tools_upgrade_regular_packages": "Actualizando ahora paquetes «normales» (no relacionados con YunoHost)…",
"tools_upgrade_cant_unhold_critical_packages": "No se pudieron liberar los paquetes críticos…", "tools_upgrade_cant_unhold_critical_packages": "No se pudo liberar los paquetes críticos…",
"tools_upgrade_cant_hold_critical_packages": "No se pudieron retener los paquetes críticos…", "tools_upgrade_cant_hold_critical_packages": "No se pudieron retener los paquetes críticos…",
"tools_upgrade_cant_both": "No se puede actualizar el sistema y las aplicaciones al mismo tiempo", "tools_upgrade_cant_both": "No se puede actualizar el sistema y las aplicaciones al mismo tiempo",
"tools_upgrade_at_least_one": "Especifique «--apps», o «--system»", "tools_upgrade_at_least_one": "Especifique «--apps», o «--system»",
"tools_update_failed_to_app_fetchlist": "No se pudo actualizar la lista de aplicaciones de YunoHost porque: {error}", "tools_update_failed_to_app_fetchlist": "No se pudo actualizar la lista de aplicaciones de YunoHost porque: {error}",
"this_action_broke_dpkg": "Esta acción rompió dpkg/APT(los gestores de paquetes del sistema)… Puede tratar de solucionar este problema conectando mediante SSH y ejecutando `sudo dpkg --configure -a`.", "this_action_broke_dpkg": "Esta acción rompió dpkg/APT(los gestores de paquetes del sistema)… Puede tratar de solucionar este problema conectando mediante SSH y ejecutando `sudo dpkg --configure -a`.",
"system_groupname_exists": "El nombre de grupo ya existe en el grupo del sistema", "system_groupname_exists": "El nombre de grupo ya existe en el grupo del sistema",
"service_reloaded_or_restarted": "Recargado o reiniciado el servicio «{service:s}»", "service_reloaded_or_restarted": "El servicio «{service:s}» ha sido recargado o reiniciado",
"service_reload_or_restart_failed": "No se pudo recargar o reiniciar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}", "service_reload_or_restart_failed": "No se pudo recargar o reiniciar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_restarted": "Reiniciado el servicio «{service:s}»", "service_restarted": "Reiniciado el servicio «{service:s}»",
"service_restart_failed": "No se pudo reiniciar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}", "service_restart_failed": "No se pudo reiniciar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_reloaded": "Recargado el servicio «{service:s}»", "service_reloaded": "El servicio «{service:s}» ha sido recargado",
"service_reload_failed": "No se pudo recargar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}", "service_reload_failed": "No se pudo recargar el servicio «{service:s}»\n\nRegistro de servicios recientes:{logs:s}",
"service_regen_conf_is_deprecated": "¡«yunohost service regen-conf» está obsoleto! Use «yunohost tools regen-conf» en su lugar.", "service_regen_conf_is_deprecated": "¡«yunohost service regen-conf» está obsoleto! Use «yunohost tools regen-conf» en su lugar.",
"service_description_yunohost-firewall": "Gestiona los puertos de conexiones abiertos y cerrados a los servicios", "service_description_yunohost-firewall": "Gestiona los puertos de conexiones abiertos y cerrados a los servicios",
@ -360,7 +360,7 @@
"service_description_php7.0-fpm": "Ejecuta aplicaciones escritas en PHP con NGINX", "service_description_php7.0-fpm": "Ejecuta aplicaciones escritas en PHP con NGINX",
"service_description_nslcd": "Maneja la conexión del intérprete de órdenes («shell») de usuario de YunoHost", "service_description_nslcd": "Maneja la conexión del intérprete de órdenes («shell») de usuario de YunoHost",
"service_description_nginx": "Sirve o proporciona acceso a todos los sitios web alojados en su servidor", "service_description_nginx": "Sirve o proporciona acceso a todos los sitios web alojados en su servidor",
"service_description_mysql": "Almacena los datos de las aplicaciones (base de datos SQL)", "service_description_mysql": "Almacena los datos de la aplicación (base de datos SQL)",
"service_description_metronome": "Gestionar las cuentas XMPP de mensajería instantánea", "service_description_metronome": "Gestionar las cuentas XMPP de mensajería instantánea",
"service_description_glances": "Supervisa la información del sistema en su servidor", "service_description_glances": "Supervisa la información del sistema en su servidor",
"service_description_fail2ban": "Protege contra ataques de fuerza bruta y otras clases de ataques desde Internet", "service_description_fail2ban": "Protege contra ataques de fuerza bruta y otras clases de ataques desde Internet",
@ -398,16 +398,16 @@
"remove_main_permission_not_allowed": "No se permite eliminar el permiso principal", "remove_main_permission_not_allowed": "No se permite eliminar el permiso principal",
"recommend_to_add_first_user": "La posinstalación ha terminado pero YunoHost necesita al menos un usuario para funcionar correctamente, debe añadir uno ejecutando «yunohost user create <nombredeusuario>» o usando la interfaz de administración.", "recommend_to_add_first_user": "La posinstalación ha terminado pero YunoHost necesita al menos un usuario para funcionar correctamente, debe añadir uno ejecutando «yunohost user create <nombredeusuario>» o usando la interfaz de administración.",
"permission_update_nothing_to_do": "No hay permisos para actualizar", "permission_update_nothing_to_do": "No hay permisos para actualizar",
"permission_updated": "Actualizado el permiso «{permission:s}» para la aplicación «{app:s}»", "permission_updated": "Actualizado el permiso «{permission:s}»",
"permission_generated": "Actualizada la base de datos de permisos", "permission_generated": "Actualizada la base de datos de permisos",
"permission_update_failed": "No se pudo actualizar el permiso", "permission_update_failed": "No se pudo actualizar el permiso «{permission}» : {error}",
"permission_name_not_valid": "Elija un nombre de permiso permitido para «{permission:s}", "permission_name_not_valid": "Elija un nombre de permiso permitido para «{permission:s}",
"permission_not_found": "No se encontró el permiso «{permission:s}» para la aplicación «{app:s}»", "permission_not_found": "No se encontró el permiso «{permission:s}»",
"permission_deletion_failed": "Falta el permiso «{permission:s}» para eliminar la aplicación «{app:s}»", "permission_deletion_failed": "No se pudo eliminar el permiso «{permission}»: {error}",
"permission_deleted": "Eliminado el permiso «{permission:s}» para la aplicación {app:s}", "permission_deleted": "Eliminado el permiso «{permission:s}»",
"permission_creation_failed": "No se pudo conceder el permiso", "permission_creation_failed": "No se pudo crear el permiso «{permission}»: {error}",
"permission_created": "Creado el permiso «{permission:s}» para la aplicación {app:s}", "permission_created": "Creado el permiso «{permission:s}»",
"permission_already_exist": "El permiso «{permission:s}» para la aplicación {app:s} ya existe", "permission_already_exist": "El permiso «{permission}» ya existe",
"permission_already_clear": "El permiso «{permission:s}» ya está definido para la aplicación {app:s}", "permission_already_clear": "El permiso «{permission:s}» ya está definido para la aplicación {app:s}",
"pattern_password_app": "Las contraseñas no pueden incluir los siguientes caracteres: {forbidden_chars}", "pattern_password_app": "Las contraseñas no pueden incluir los siguientes caracteres: {forbidden_chars}",
"need_define_permission_before": "Redefina los permisos ejecutando «yunohost user permission add -u USUARIO» antes de eliminar un grupo permitido", "need_define_permission_before": "Redefina los permisos ejecutando «yunohost user permission add -u USUARIO» antes de eliminar un grupo permitido",
@ -417,7 +417,7 @@
"migrations_running_forward": "Ejecutando migración {id}…", "migrations_running_forward": "Ejecutando migración {id}…",
"migrations_pending_cant_rerun": "Esas migraciones están aún pendientes, así que no se pueden volver a ejecutar: {ids}", "migrations_pending_cant_rerun": "Esas migraciones están aún pendientes, así que no se pueden volver a ejecutar: {ids}",
"migrations_not_pending_cant_skip": "Esas migraciones no están pendientes, así que no pueden ser omitidas: {ids}", "migrations_not_pending_cant_skip": "Esas migraciones no están pendientes, así que no pueden ser omitidas: {ids}",
"migrations_no_such_migration": "No hay ninguna migración llamada {id}", "migrations_no_such_migration": "No hay ninguna migración llamada «{id}»",
"migrations_no_migrations_to_run": "No hay migraciones que ejecutar", "migrations_no_migrations_to_run": "No hay migraciones que ejecutar",
"migrations_need_to_accept_disclaimer": "Para ejecutar la migración {id} debe aceptar el siguiente descargo de responsabilidad:\n---\n{disclaimer}\n---\nSi acepta ejecutar la migración, vuelva a ejecutar la orden con la opción «--accept-disclaimer».", "migrations_need_to_accept_disclaimer": "Para ejecutar la migración {id} debe aceptar el siguiente descargo de responsabilidad:\n---\n{disclaimer}\n---\nSi acepta ejecutar la migración, vuelva a ejecutar la orden con la opción «--accept-disclaimer».",
"migrations_must_provide_explicit_targets": "Necesita proporcionar objetivos explícitos al usar «--skip» or «--force-rerun»", "migrations_must_provide_explicit_targets": "Necesita proporcionar objetivos explícitos al usar «--skip» or «--force-rerun»",
@ -426,30 +426,30 @@
"migrations_list_conflict_pending_done": "No puede usar «--previous» y «--done» al mismo tiempo.", "migrations_list_conflict_pending_done": "No puede usar «--previous» y «--done» al mismo tiempo.",
"migrations_exclusive_options": "«--auto», «--skip», and «--force-rerun» son opciones mutuamente excluyentes.", "migrations_exclusive_options": "«--auto», «--skip», and «--force-rerun» son opciones mutuamente excluyentes.",
"migrations_failed_to_load_migration": "No se pudo cargar la migración {id}: {error}", "migrations_failed_to_load_migration": "No se pudo cargar la migración {id}: {error}",
"migrations_dependencies_not_satisfied": "No se puede ejecutar la migración {id} porque primero necesita ejecutar estas migraciones: {dependencies_id}", "migrations_dependencies_not_satisfied": "Ejecutar estas migraciones: «{dependencies_id}» antes de migrar {id}.",
"migrations_cant_reach_migration_file": "No se pudo acceder los archivos de migración en la ruta %s", "migrations_cant_reach_migration_file": "No se pudo acceder a los archivos de migración en la ruta «%s»",
"migrations_already_ran": "Esas migraciones ya se han realizado: {ids}", "migrations_already_ran": "Esas migraciones ya se han realizado: {ids}",
"migration_0011_update_LDAP_schema": "Actualizando el esquema de LDAP…", "migration_0011_update_LDAP_schema": "Actualizando el esquema de LDAP…",
"migration_0011_update_LDAP_database": "Actualizando la base de datos de LDAP…", "migration_0011_update_LDAP_database": "Actualizando la base de datos de LDAP…",
"migration_0011_rollback_success": "Sistema revertido.", "migration_0011_rollback_success": "Sistema revertido.",
"migration_0011_migration_failed_trying_to_rollback": "Migración fallida… intentando revertir el sistema.", "migration_0011_migration_failed_trying_to_rollback": "No se pudo migrar… intentando revertir el sistema.",
"migration_0011_migrate_permission": "Migrando permisos desde la configuración de las aplicaciones a LDAP…", "migration_0011_migrate_permission": "Migrando permisos desde la configuración de las aplicaciones a LDAP…",
"migration_0011_LDAP_update_failed": "No se pudo actualizar LDAP. Error: {error:s}", "migration_0011_LDAP_update_failed": "No se pudo actualizar LDAP. Error: {error:s}",
"migration_0011_LDAP_config_dirty": "Parece que ha personalizado la configuración de LDAP. Para esta migración se necesita actualizar la configuración de LDAP.\nNecesita guardar su configuración actual, reiniciar la configuración original ejecutando «yunohost tools regen-conf -f» y reintentar la migración", "migration_0011_LDAP_config_dirty": "Parece que ha personalizado la configuración de LDAP. Para esta migración se necesita actualizar la configuración de LDAP.\nNecesita guardar su configuración actual, reiniciar la configuración original ejecutando «yunohost tools regen-conf -f» y reintentar la migración",
"migration_0011_done": "Migración correcta. Ahora puede gestionar los grupos de usuarios.", "migration_0011_done": "Migración finalizada. Ahora puede gestionar los grupos de usuarios.",
"migration_0011_create_group": "Creando un grupo para cada usuario…", "migration_0011_create_group": "Creando un grupo para cada usuario…",
"migration_0011_can_not_backup_before_migration": "No se pudo respaldar el sistema antes de la migración. Error: {error:s}", "migration_0011_can_not_backup_before_migration": "El respaldo del sistema no se pudo completar antes de que la migración fallase. Error: {error:s}",
"migration_0011_backup_before_migration": "Creando un respaldo de la base de datos de LDAP y de la configuración de las aplicaciones antes de la migración real.", "migration_0011_backup_before_migration": "Creando un respaldo de la base de datos de LDAP y de la configuración de las aplicaciones antes de la migración real.",
"migration_0009_not_needed": "La migración ya ocurrió de algún modo… (?) Omitiendo.", "migration_0009_not_needed": "La migración ya ocurrió de algún modo… (?) Omitiendo.",
"migration_0008_no_warning": "No se ha detectado ningún riesgo importante con respecto a la anulación de su configuración SSH ¡sin embargo uno nunca puede estar absolutamente seguro ;)! Ejecute la migración para anularla. Por otra parte, puede omitir la migración aunque no esté recomendado.", "migration_0008_no_warning": "Ignorar su configuración SSH debería ser seguro ¡aunque esto no se puede prometer! Ejecute la migración para ignorarla. Por otra parte puede omitir la migración, aunque no se recomienda.",
"migration_0008_warning": "Si entiende esos avisos y permite a YunoHost anular su configuración actual, ejecute la migración. Por otra parte puede omitir la migración, aunque no se recomienda.", "migration_0008_warning": "Si entiende esos avisos y quiere que YunoHost ignore su configuración actual, ejecute la migración. Por otra parte puede omitir la migración, aunque no se recomienda.",
"migration_0008_dsa": "• Se desactivará la clave DSA. Así que podría tener que anular un aviso espeluznante de su cliente SSH y volver a comprobar la huella de su servidor;", "migration_0008_dsa": "• Se desactivará la clave DSA. Así que podría tener que anular un aviso espeluznante de su cliente SSH y volver a comprobar la huella de su servidor;",
"migration_0008_root": "• No podrá conectarse como «root» a través de SSH. En su lugar debe usar el usuario «admin»;", "migration_0008_root": "• No podrá conectarse como «root» a través de SSH. En su lugar debe usar el usuario «admin»;",
"migration_0008_port": "• Tendrá que conectarse usando el puerto 22 en vez de su actual puerto SSH personalizado. No dude en reconfigurarlo;", "migration_0008_port": "• Tendrá que conectarse usando el puerto 22 en vez de su actual puerto SSH personalizado. No dude en reconfigurarlo;",
"migration_0008_general_disclaimer": "Para mejorar la seguridad de su servidor, es recomendable permitir a YunoHost gestionar la configuración de SSH. Su actual configuración de SSH difiere de la recomendación. Si permite a YunoHost reconfigurarla, la manera en la que conecta con su servidor a través de SSH cambiará así:", "migration_0008_general_disclaimer": "Para mejorar la seguridad de su servidor, es recomendable permitir a YunoHost gestionar la configuración de SSH. Su actual configuración de SSH difiere de la recomendación. Si permite a YunoHost reconfigurarla, la manera en la que conecta con su servidor a través de SSH cambiará así:",
"migration_0007_cannot_restart": "No se puede reiniciar SSH después de intentar cancelar la migración número 6.", "migration_0007_cannot_restart": "No se puede reiniciar SSH después de intentar cancelar la migración número 6.",
"migration_0007_cancelled": "YunoHost no ha podido mejorar el modo en el que se gestiona su configuración de SSH.", "migration_0007_cancelled": "No se pudo mejorar el modo en el que se gestiona su configuración de SSH.",
"migration_0006_disclaimer": "YunoHost espera ahora que las contraseñas de «admin» y «root» estén sincronizadas. Al ejecutar esta migración, su contraseña de «root» será reemplazada por la contraseña de administración.", "migration_0006_disclaimer": "YunoHost espera ahora que las contraseñas de «admin» y «root» estén sincronizadas. Esta migración reemplaza su contraseña de «root» por la contraseña de «admin».",
"migration_0005_not_enough_space": "Tenga suficiente espacio libre disponible en {path} para ejecutar la migración.", "migration_0005_not_enough_space": "Tenga suficiente espacio libre disponible en {path} para ejecutar la migración.",
"migration_0005_postgresql_96_not_installed": "⸘PostgreSQL 9.4 está instalado pero no PostgreSQL 9.6‽ Algo raro podría haber ocurrido en su sistema:(…", "migration_0005_postgresql_96_not_installed": "⸘PostgreSQL 9.4 está instalado pero no PostgreSQL 9.6‽ Algo raro podría haber ocurrido en su sistema:(…",
"migration_0005_postgresql_94_not_installed": "PostgreSQL no estaba instalado en su sistema. Nada que hacer.", "migration_0005_postgresql_94_not_installed": "PostgreSQL no estaba instalado en su sistema. Nada que hacer.",
@ -502,12 +502,12 @@
"log_user_delete": "Eliminar usuario «{}»", "log_user_delete": "Eliminar usuario «{}»",
"log_user_create": "Añadir usuario «{}»", "log_user_create": "Añadir usuario «{}»",
"log_regen_conf": "Regenerar la configuración del sistema «{}»", "log_regen_conf": "Regenerar la configuración del sistema «{}»",
"log_letsencrypt_cert_renew": "Renovar el certificado «{}» de Let's encrypt", "log_letsencrypt_cert_renew": "Renovar el certificado «{}» de Let's Encrypt",
"log_selfsigned_cert_install": "Instalar certificado autofirmado en el dominio «{}»", "log_selfsigned_cert_install": "Instalar certificado autofirmado en el dominio «{}»",
"log_permission_update": "Actualizar permiso «{}» para la aplicación «{}»", "log_permission_update": "Actualizar permiso «{}» para la aplicación «{}»",
"log_permission_remove": "Eliminar permiso «{}»", "log_permission_remove": "Eliminar permiso «{}»",
"log_permission_add": "Añadir el permiso «{}» para la aplicación «{}»", "log_permission_add": "Añadir el permiso «{}» para la aplicación «{}»",
"log_letsencrypt_cert_install": "Instalar un certificado de Let's encrypt en el dominio «{}»", "log_letsencrypt_cert_install": "Instalar un certificado de Let's Encrypt en el dominio «{}»",
"log_dyndns_update": "Actualizar la IP asociada con su subdominio de YunoHost «{}»", "log_dyndns_update": "Actualizar la IP asociada con su subdominio de YunoHost «{}»",
"log_dyndns_subscribe": "Subscribirse a un subdomino de YunoHost «{}»", "log_dyndns_subscribe": "Subscribirse a un subdomino de YunoHost «{}»",
"log_domain_remove": "Eliminar el dominio «{}» de la configuración del sistema", "log_domain_remove": "Eliminar el dominio «{}» de la configuración del sistema",
@ -536,14 +536,14 @@
"log_category_404": "La categoría de registro «{category}» no existe", "log_category_404": "La categoría de registro «{category}» no existe",
"log_corrupted_md_file": "El archivo de metadatos YAML asociado con el registro está dañado: «{md_file}\nError: {error}»", "log_corrupted_md_file": "El archivo de metadatos YAML asociado con el registro está dañado: «{md_file}\nError: {error}»",
"hook_json_return_error": "No se pudo leer la respuesta del gancho {path:s}. Error: {msg:s}. Contenido sin procesar: {raw_content}", "hook_json_return_error": "No se pudo leer la respuesta del gancho {path:s}. Error: {msg:s}. Contenido sin procesar: {raw_content}",
"group_update_failed": "No se pudo actualizar el grupo «{group}»", "group_update_failed": "No se pudo actualizar el grupo «{group}»: {error}",
"group_updated": "Grupo «{group}» actualizado", "group_updated": "Grupo «{group}» actualizado",
"group_unknown": "El grupo «{group:s}» es desconocido", "group_unknown": "El grupo «{group:s}» es desconocido",
"group_info_failed": "No se pudo mostrar la información del grupo", "group_info_failed": "No se pudo mostrar la información del grupo",
"group_deletion_not_allowed": "No se puede eliminar el grupo {group:s} manualmente.", "group_deletion_not_allowed": "No se puede eliminar el grupo {group:s} manualmente.",
"group_deletion_failed": "No se pudo eliminar el grupo «{group}»", "group_deletion_failed": "No se pudo eliminar el grupo «{group}»: {error}",
"group_deleted": "Eliminado el grupo «{group}»", "group_deleted": "Eliminado el grupo «{group}»",
"group_creation_failed": "No se pudo crear el grupo «{group}»", "group_creation_failed": "No se pudo crear el grupo «{group}»: {error}",
"group_created": "Creado el grupo «{group}»", "group_created": "Creado el grupo «{group}»",
"group_name_already_exist": "El grupo {name:s} ya existe", "group_name_already_exist": "El grupo {name:s} ya existe",
"group_already_disallowed": "El grupo «{group:s}» ya tiene desactivado el permiso «{permission:s}» para la aplicación «{app:s}»", "group_already_disallowed": "El grupo «{group:s}» ya tiene desactivado el permiso «{permission:s}» para la aplicación «{app:s}»",
@ -577,12 +577,12 @@
"domain_dns_conf_is_just_a_recommendation": "Esta orden muestra la configuración *recomendada*. No configura el DNS en realidad. Es su responsabilidad configurar la zona de DNS en su registrador según esta recomendación.", "domain_dns_conf_is_just_a_recommendation": "Esta orden muestra la configuración *recomendada*. No configura el DNS en realidad. Es su responsabilidad configurar la zona de DNS en su registrador según esta recomendación.",
"dpkg_lock_not_available": "Esta orden no se puede ejecutar en este momento porque otro programa parece que está usando el bloqueo de dpkg (el gestor de paquetes del sistema)", "dpkg_lock_not_available": "Esta orden no se puede ejecutar en este momento porque otro programa parece que está usando el bloqueo de dpkg (el gestor de paquetes del sistema)",
"dpkg_is_broken": "No puede hacer esto en este momento porque dpkg/apt (los gestores de paquetes del sistema) parecen estar en un estado roto... Puede tratar de solucionar este problema conectando a través de SSH y ejecutando `sudo dpkg --configure -a`.", "dpkg_is_broken": "No puede hacer esto en este momento porque dpkg/apt (los gestores de paquetes del sistema) parecen estar en un estado roto... Puede tratar de solucionar este problema conectando a través de SSH y ejecutando `sudo dpkg --configure -a`.",
"confirm_app_install_thirdparty": AVISO! Instalar aplicaciones de terceros podría comprometer la integridad y seguridad de su sistema. Probablemente NO debería instalarlas salvo que sepa lo que está haciendo. ¿Está dispuesto a correr ese riesgo? [{answers:s}] ", "confirm_app_install_thirdparty": PELIGRO! Esta aplicación no forma parte del catálogo de aplicaciones de YunoHost. Instalar aplicaciones de terceros podría comprometer la integridad y seguridad de su sistema. Probablemente NO debería instalarla salvo que sepa lo que está haciendo. No tendrá NINGUNA AYUDA si esta aplicación no funciona o rompe su sistema… Si está dispuesto a aceptar ese riesgo de todas formas, escriba «{answers:s}»",
"confirm_app_install_danger": AVISO! Esta aplicación es aún experimental (si no está funcionando expresamente) y ¡es probable que rompa su sistema! Probablemente NO debería instalarla salvo que sepa lo que está haciendo. ¿Está dispuesto a correr ese riesgo? [{answers:s}] ", "confirm_app_install_danger": PELIGRO! ¡Esta aplicación es conocida por ser aún experimental (o no funciona explícitamente)! Probablemente NO debería instalarla salvo que sepa lo que está haciendo. No tendrá NINGUNA AYUDA si esta aplicación no funciona o rompe su sistema… Si está dispuesto a aceptar ese riesgo de todas formas, escriba «{answers:s}»",
"confirm_app_install_warning": "Aviso: esta aplicación puede funcionar pero no está bien integrada en YunoHost. Algunas herramientas como la autentificación única y respaldo/restauración podrían no estar disponibles. ¿Instalar de todos modos? [{answers:s}] ", "confirm_app_install_warning": "Aviso: esta aplicación puede funcionar pero no está bien integrada en YunoHost. Algunas herramientas como la autentificación única y respaldo/restauración podrían no estar disponibles. ¿Instalar de todos modos? [{answers:s}] ",
"backup_unable_to_organize_files": "No se pudo usar el método rápido de organización de los archivos en el archivo", "backup_unable_to_organize_files": "No se pudo usar el método rápido de organización de los archivos en el archivo",
"backup_permission": "Permiso de respaldo para la aplicación {app:s}", "backup_permission": "Permiso de respaldo para la aplicación {app:s}",
"backup_output_symlink_dir_broken": "Tiene un enlace simbólico roto en vez del directorio «{path:s}» de su archivo. Puede que tenga una configuración específica para respaldar sus datos en otro sistema de archivos, en este caso probablemente olvidó remontar o conectar su disco duro o clave USB.", "backup_output_symlink_dir_broken": "El directorio de su archivo «{path:s}» es un enlace simbólico roto. Tal vez olvidó (re)montarlo o conectarlo al medio de almacenamiento al que apunta.",
"backup_mount_archive_for_restore": "Preparando el archivo para la restauración…", "backup_mount_archive_for_restore": "Preparando el archivo para la restauración…",
"backup_method_tar_finished": "Creado el archivo TAR de respaldo", "backup_method_tar_finished": "Creado el archivo TAR de respaldo",
"backup_method_custom_finished": "Terminado el método «{method:s}» de respaldo personalizado", "backup_method_custom_finished": "Terminado el método «{method:s}» de respaldo personalizado",
@ -595,18 +595,47 @@
"apps_permission_restoration_failed": "Otorgar el permiso «{permission:s}» para restaurar {app:s}", "apps_permission_restoration_failed": "Otorgar el permiso «{permission:s}» para restaurar {app:s}",
"apps_permission_not_found": "No se han encontrado permisos para las aplicaciones instaladas", "apps_permission_not_found": "No se han encontrado permisos para las aplicaciones instaladas",
"app_upgrade_several_apps": "Las siguientes aplicaciones se actualizarán: {apps}", "app_upgrade_several_apps": "Las siguientes aplicaciones se actualizarán: {apps}",
"app_start_restore": "Restaurando aplicación {app}…", "app_start_restore": "Restaurando aplicación «{app}»…",
"app_start_backup": "Obteniendo archivos para el respaldo de {app}…", "app_start_backup": "Obteniendo archivos para el respaldo de «{app}»…",
"app_start_remove": "Eliminando aplicación {app}…", "app_start_remove": "Eliminando aplicación «{app}»…",
"app_start_install": "Instalando aplicación {app}…", "app_start_install": "Instalando aplicación «{app}»…",
"app_not_upgraded": "Error al actualizar la aplicación «{failed_app}» y como consecuencia se han cancelado las actualizaciones de las siguientes aplicaciones: {apps}", "app_not_upgraded": "Error al actualizar la aplicación «{failed_app}» y como consecuencia se han cancelado las actualizaciones de las siguientes aplicaciones: {apps}",
"app_action_cannot_be_ran_because_required_services_down": "Esta aplicación necesita algunos servicios que no están funcionando ahora. Antes de continuar, debería intentar reiniciar los siguientes servicios (y posiblemente investigar por qué no funcionan): {services}", "app_action_cannot_be_ran_because_required_services_down": "Estos servicios necesarios deberían estar funcionando para ejecutar esta acción: {services}. Pruebe a reiniciarlos para continuar (y posiblemente investigar por qué están caídos).",
"already_up_to_date": "Nada que hacer. Todo está actualizado.", "already_up_to_date": "Nada que hacer. Todo está actualizado.",
"admin_password_too_long": "Elija una contraseña de menos de 127 caracteres", "admin_password_too_long": "Elija una contraseña de menos de 127 caracteres",
"aborting": "Cancelando.", "aborting": "Cancelando.",
"app_upgrade_stopped": "Se ha detenido la actualización de todas las aplicaciones para prevenir un posible daño porque la aplicación anterior no se pudo actualizar", "app_upgrade_stopped": "Se ha detenido la actualización de todas las aplicaciones para prevenir un posible daño porque una aplicación no se pudo actualizar",
"app_action_broke_system": "Esta acción parece que ha roto estos importantes servicios: {services}", "app_action_broke_system": "Esta acción parece que ha roto estos importantes servicios: {services}",
"operation_interrupted": "¿Ha sido interrumpida la operación manualmente?", "operation_interrupted": "¿Ha sido interrumpida la operación manualmente?",
"apps_already_up_to_date": "Todas las aplicaciones están ya actualizadas", "apps_already_up_to_date": "Todas las aplicaciones están ya actualizadas",
"dyndns_provider_unreachable": "No se puede conectar con el proveedor de Dyndns {provider}: o su YunoHost no está correctamente conectado a Internet o el servidor de dynette está caído." "dyndns_provider_unreachable": "No se puede conectar con el proveedor de Dyndns {provider}: o su YunoHost no está correctamente conectado a Internet o el servidor de dynette está caído.",
"group_already_exist": "El grupo {group} ya existe",
"group_already_exist_on_system": "El grupo {group} ya existe en los grupos del sistema",
"group_cannot_be_edited": "El grupo {group} no se puede editar manualmente.",
"group_cannot_be_deleted": "El grupo {group} no se puede eliminar manualmente.",
"group_user_already_in_group": "El usuario {user} ya está en el grupo {group}",
"group_user_not_in_group": "El usuario {user} no está en el grupo {group}",
"log_permission_create": "Crear permiso «{}»",
"log_permission_delete": "Eliminar permiso «{}»",
"log_permission_urls": "Actualizar URLs relacionadas con el permiso «{}»",
"log_user_group_create": "Crear grupo «{}»",
"log_user_permission_update": "Actualizar los accesos para el permiso «{}»",
"log_user_permission_reset": "Restablecer permiso «{}»",
"migration_0011_failed_to_remove_stale_object": "No se pudo eliminar el objeto obsoleto {dn}: {error}",
"permission_already_allowed": "El grupo «{group}» ya tiene el permiso «{permission}» activado",
"permission_already_disallowed": "El grupo «{group}» ya tiene el permiso «{permission}» desactivado",
"permission_cannot_remove_main": "No está permitido eliminar un permiso principal",
"user_already_exists": "El usuario «{user}» ya existe",
"app_full_domain_unavailable": "Lamentablemente esta aplicación tiene que instalarse en un dominio propio pero ya hay otras aplicaciones instaladas en el dominio «{domain}». Podría usar un subdomino dedicado a esta aplicación en su lugar.",
"app_install_failed": "No se pudo instalar {app}: {error}",
"app_install_script_failed": "Ha ocurrido un error en el guión de instalación de la aplicación",
"group_cannot_edit_all_users": "El grupo «all_users» no se puede editar manualmente. Es un grupo especial destinado a contener todos los usuarios registrados en YunoHost",
"group_cannot_edit_visitors": "El grupo «visitors» no se puede editar manualmente. Es un grupo especial que representa a los visitantes anónimos",
"group_cannot_edit_primary_group": "El grupo «{group}» no se puede editar manualmente. Es el grupo primario destinado a contener solo un usuario específico.",
"log_permission_url": "Actualizar la URL relacionada con el permiso «{}»",
"migration_0011_slapd_config_will_be_overwritten": "Parece que ha editado manualmente la configuración de slapd. Para esta migración crítica, YunoHost necesita forzar la actualización de la configuración de slapd. Los archivos originales se respaldarán en {conf_backup_folder}.",
"permission_already_up_to_date": "El permiso no se ha actualizado porque las peticiones de incorporación o eliminación ya coinciden con el estado actual.",
"permission_currently_allowed_for_visitors": "Este permiso se concede actualmente a los visitantes además de otros grupos. Probablemente quiere o eliminar el permiso de «visitors» o eliminar los otros grupos a los que está otorgado actualmente.",
"permission_currently_allowed_for_all_users": "Este permiso se concede actualmente a todos los usuarios además de los otros grupos. Probablemente quiere o eliminar el permiso de «all_users» o eliminar los otros grupos a los que está otorgado actualmente.",
"permission_require_account": "El permiso {permission} solo tiene sentido para usuarios con una cuenta y, por lo tanto, no se puede activar para visitantes."
} }

View file

@ -30,10 +30,10 @@
"app_unsupported_remote_type": "Ce type de commande à distance utilisé pour cette application n'est pas supporté", "app_unsupported_remote_type": "Ce type de commande à distance utilisé pour cette application n'est pas supporté",
"app_upgrade_failed": "Impossible de mettre à jour {app:s}", "app_upgrade_failed": "Impossible de mettre à jour {app:s}",
"app_upgraded": "{app:s} mis à jour", "app_upgraded": "{app:s} mis à jour",
"appslist_fetched": "La liste dapplications {appslist:s} récupérée", "appslist_fetched": "La liste dapplications mise à jour '{appslist:s}'",
"appslist_removed": "La liste dapplications {appslist:s} a été supprimée", "appslist_removed": "La liste d'applications '{appslist:s}' a été supprimée",
"appslist_retrieve_error": "Impossible de récupérer la liste dapplications distante {appslist:s} : {error:s}", "appslist_retrieve_error": "Impossible de récupérer la liste dapplications distante '{appslist:s}' : {error:s}",
"appslist_unknown": "La liste dapplications {appslist:s} est inconnue.", "appslist_unknown": "La liste dapplications '{appslist:s}' est inconnue.",
"ask_current_admin_password": "Mot de passe dadministration actuel", "ask_current_admin_password": "Mot de passe dadministration actuel",
"ask_email": "Adresse de courriel", "ask_email": "Adresse de courriel",
"ask_firstname": "Prénom", "ask_firstname": "Prénom",
@ -75,9 +75,9 @@
"dnsmasq_isnt_installed": "dnsmasq ne semble pas être installé, veuillez lancer 'apt-get remove bind9 && apt-get install dnsmasq'", "dnsmasq_isnt_installed": "dnsmasq ne semble pas être installé, veuillez lancer 'apt-get remove bind9 && apt-get install dnsmasq'",
"domain_cert_gen_failed": "Impossible de générer le certificat", "domain_cert_gen_failed": "Impossible de générer le certificat",
"domain_created": "Le domaine a été créé", "domain_created": "Le domaine a été créé",
"domain_creation_failed": "Impossible de créer le domaine", "domain_creation_failed": "Impossible de créer le domaine {domain}: {error}",
"domain_deleted": "Le domaine a été supprimé", "domain_deleted": "Le domaine a été supprimé",
"domain_deletion_failed": "Impossible de supprimer le domaine", "domain_deletion_failed": "Impossible de supprimer le domaine {domain}: {error}",
"domain_dyndns_already_subscribed": "Vous avez déjà souscris à un domaine DynDNS", "domain_dyndns_already_subscribed": "Vous avez déjà souscris à un domaine DynDNS",
"domain_dyndns_invalid": "Domaine incorrect pour un usage avec DynDNS", "domain_dyndns_invalid": "Domaine incorrect pour un usage avec DynDNS",
"domain_dyndns_root_unknown": "Domaine DynDNS principal inconnu", "domain_dyndns_root_unknown": "Domaine DynDNS principal inconnu",
@ -120,22 +120,22 @@
"ldap_initialized": "Lannuaire LDAP initialisé", "ldap_initialized": "Lannuaire LDAP initialisé",
"license_undefined": "indéfinie", "license_undefined": "indéfinie",
"mail_alias_remove_failed": "Impossible de supprimer lalias de courriel '{mail:s}'", "mail_alias_remove_failed": "Impossible de supprimer lalias de courriel '{mail:s}'",
"mail_domain_unknown": "Le domaine '{domain:s}' pour l'adresse de courriel est inconnu", "mail_domain_unknown": "Le domaine '{domain:s}' de cette adress de courriel n'est pas valide. Merci d'utiliser un domain administré par ce serveur.",
"mail_forward_remove_failed": "Impossible de supprimer le courriel de transfert '{mail:s}'", "mail_forward_remove_failed": "Impossible de supprimer le courriel de transfert '{mail:s}'",
"main_domain_change_failed": "Impossible de modifier le domaine principal", "main_domain_change_failed": "Impossible de modifier le domaine principal",
"main_domain_changed": "Le domaine principal a été modifié", "main_domain_changed": "Le domaine principal modifié",
"monitor_disabled": "La supervision du serveur a été désactivé", "monitor_disabled": "Surveillance du serveur est maintenant arrêté",
"monitor_enabled": "La supervision du serveur a été activé", "monitor_enabled": "La supervision du serveur est maintenant allumée",
"monitor_glances_con_failed": "Impossible de se connecter au serveur Glances", "monitor_glances_con_failed": "Impossible de se connecter au serveur Glances",
"monitor_not_enabled": "Le suivi de létat du serveur nest pas activé", "monitor_not_enabled": "Le suivi de létat du serveur nest pas activé",
"monitor_period_invalid": "Période de temps incorrecte", "monitor_period_invalid": "Période de temps incorrecte",
"monitor_stats_file_not_found": "Le fichier de statistiques est introuvable", "monitor_stats_file_not_found": "Impossible de trouver le fichier de statistiques",
"monitor_stats_no_update": "Aucune donnée de létat du serveur à mettre à jour", "monitor_stats_no_update": "Aucune donnée de létat du serveur à mettre à jour",
"monitor_stats_period_unavailable": "Aucune statistique nest disponible pour la période", "monitor_stats_period_unavailable": "Aucune statistique nest disponible pour la période",
"mountpoint_unknown": "Point de montage inconnu", "mountpoint_unknown": "Point de montage inconnu",
"mysql_db_creation_failed": "Impossible de créer la base de données MySQL", "mysql_db_creation_failed": "Impossible de créer la base de données MySQL",
"mysql_db_init_failed": "Impossible dinitialiser la base de données MySQL", "mysql_db_init_failed": "Impossible d'initialiser la base de données MySQL",
"mysql_db_initialized": "La base de données MySQL a été initialisée", "mysql_db_initialized": "La base de données MySQL est maintenant initialisée",
"network_check_mx_ko": "Lenregistrement DNS MX nest pas défini", "network_check_mx_ko": "Lenregistrement DNS MX nest pas défini",
"network_check_smtp_ko": "Le trafic courriel sortant (port 25 SMTP) semble bloqué par votre réseau", "network_check_smtp_ko": "Le trafic courriel sortant (port 25 SMTP) semble bloqué par votre réseau",
"network_check_smtp_ok": "Le trafic courriel sortant (port 25 SMTP) nest pas bloqué", "network_check_smtp_ok": "Le trafic courriel sortant (port 25 SMTP) nest pas bloqué",
@ -155,7 +155,7 @@
"path_removal_failed": "Impossible de supprimer le chemin {:s}", "path_removal_failed": "Impossible de supprimer le chemin {:s}",
"pattern_backup_archive_name": "Doit être un nom de fichier valide avec un maximum de 30 caractères, et composé de caractères alphanumériques et -_. uniquement", "pattern_backup_archive_name": "Doit être un nom de fichier valide avec un maximum de 30 caractères, et composé de caractères alphanumériques et -_. uniquement",
"pattern_domain": "Doit être un nom de domaine valide (ex : mon-domaine.fr)", "pattern_domain": "Doit être un nom de domaine valide (ex : mon-domaine.fr)",
"pattern_email": "Doit être une adresse de courriel valide (ex. : pseudo@domaine.fr)", "pattern_email": "Doit être une adresse de courriel valide (ex. : pseudo@example.com)",
"pattern_firstname": "Doit être un prénom valide", "pattern_firstname": "Doit être un prénom valide",
"pattern_lastname": "Doit être un nom valide", "pattern_lastname": "Doit être un nom valide",
"pattern_listname": "Doit être composé uniquement de caractères alphanumériques et de tirets bas (aussi appelé tiret du 8 ou underscore)", "pattern_listname": "Doit être composé uniquement de caractères alphanumériques et de tirets bas (aussi appelé tiret du 8 ou underscore)",
@ -183,7 +183,7 @@
"service_add_configuration": "Ajout du fichier de configuration {file:s}", "service_add_configuration": "Ajout du fichier de configuration {file:s}",
"service_add_failed": "Impossible dajouter le service '{service:s}'", "service_add_failed": "Impossible dajouter le service '{service:s}'",
"service_added": "Le service '{service:s}' ajouté", "service_added": "Le service '{service:s}' ajouté",
"service_already_started": "Le service '{service:s}' est déjà démarré", "service_already_started": "Le service '{service:s}' est déjà en cours d'exécution",
"service_already_stopped": "Le service '{service:s}' est déjà arrêté", "service_already_stopped": "Le service '{service:s}' est déjà arrêté",
"service_cmd_exec_failed": "Impossible dexécuter la commande '{command:s}'", "service_cmd_exec_failed": "Impossible dexécuter la commande '{command:s}'",
"service_conf_file_backed_up": "Le fichier de configuration '{conf}' a été sauvegardé dans '{backup}'", "service_conf_file_backed_up": "Le fichier de configuration '{conf}' a été sauvegardé dans '{backup}'",
@ -204,7 +204,7 @@
"service_disabled": "Le service '{service:s}' a été désactivé", "service_disabled": "Le service '{service:s}' a été désactivé",
"service_enable_failed": "Impossible dactiver le service '{service:s}'\n\nJournaux historisés récents : {logs:s}", "service_enable_failed": "Impossible dactiver le service '{service:s}'\n\nJournaux historisés récents : {logs:s}",
"service_enabled": "Le service '{service:s}' a été activé", "service_enabled": "Le service '{service:s}' a été activé",
"service_no_log": "Aucun journal historisé à afficher pour le service '{service:s}'", "service_no_log": "Aucun journal à afficher pour le service '{service:s}'",
"service_regenconf_dry_pending_applying": "Vérification des configurations en attentes qui pourraient être appliquées au le service '{service}' …", "service_regenconf_dry_pending_applying": "Vérification des configurations en attentes qui pourraient être appliquées au le service '{service}' …",
"service_regenconf_failed": "Impossible de régénérer la configuration pour les services : {services}", "service_regenconf_failed": "Impossible de régénérer la configuration pour les services : {services}",
"service_regenconf_pending_applying": "Application des configurations en attentes pour le service '{service}' …", "service_regenconf_pending_applying": "Application des configurations en attentes pour le service '{service}' …",
@ -236,19 +236,19 @@
"upnp_enabled": "UPnP activé", "upnp_enabled": "UPnP activé",
"upnp_port_open_failed": "Impossible douvrir les ports UPnP", "upnp_port_open_failed": "Impossible douvrir les ports UPnP",
"user_created": "Lutilisateur créé", "user_created": "Lutilisateur créé",
"user_creation_failed": "Impossible de créer lutilisateur", "user_creation_failed": "Impossible de créer lutilisateur {user}: {error}",
"user_deleted": "Lutilisateur supprimé", "user_deleted": "Lutilisateur supprimé",
"user_deletion_failed": "Impossible de supprimer lutilisateur", "user_deletion_failed": "Impossible de supprimer lutilisateur {user}: {error}",
"user_home_creation_failed": "Impossible de créer le dossier personnel de lutilisateur", "user_home_creation_failed": "Impossible de créer le dossier personnel de lutilisateur",
"user_info_failed": "Impossible de récupérer les informations de lutilisateur", "user_info_failed": "Impossible de récupérer les informations de lutilisateur",
"user_unknown": "L'utilisateur {user:s} est inconnu", "user_unknown": "L'utilisateur {user:s} est inconnu",
"user_update_failed": "Impossible de modifier lutilisateur", "user_update_failed": "Impossible de mettre à jour l'utilisateur {utilisateur}: {erreur}",
"user_updated": "Lutilisateur a été modifié", "user_updated": "Lutilisateur a été modifié",
"yunohost_already_installed": "YunoHost est déjà installé", "yunohost_already_installed": "YunoHost est déjà installé",
"yunohost_ca_creation_failed": "Impossible de créer lautorité de certification", "yunohost_ca_creation_failed": "Impossible de créer lautorité de certification",
"yunohost_configured": "YunoHost maintenant configuré", "yunohost_configured": "YunoHost est maintenant configuré",
"yunohost_installing": "L'installation de YunoHost est en cours …", "yunohost_installing": "L'installation de YunoHost est en cours …",
"yunohost_not_installed": "YunoHost nest pas ou pas correctement installé. Veuillez exécuter 'yunohost tools postinstall'", "yunohost_not_installed": "YunoHost n'est pas correctement installé. Veuillez exécuter 'yunohost tools postinstall'",
"certmanager_attempt_to_replace_valid_cert": "Vous êtes en train de vouloir remplacer un certificat correct et valide pour le domaine {domain:s} ! (Utilisez --force pour contourner cela)", "certmanager_attempt_to_replace_valid_cert": "Vous êtes en train de vouloir remplacer un certificat correct et valide pour le domaine {domain:s} ! (Utilisez --force pour contourner cela)",
"certmanager_domain_unknown": "Domaine {domain:s} inconnu", "certmanager_domain_unknown": "Domaine {domain:s} inconnu",
"certmanager_domain_cert_not_selfsigned": "Le certificat du domaine {domain:s} nest pas auto-signé. Voulez-vous vraiment le remplacer ? (Utilisez --force pour cela)", "certmanager_domain_cert_not_selfsigned": "Le certificat du domaine {domain:s} nest pas auto-signé. Voulez-vous vraiment le remplacer ? (Utilisez --force pour cela)",
@ -280,13 +280,13 @@
"certmanager_domain_not_resolved_locally": "Le domaine {domain:s} ne peut être résolu depuis votre serveur YunoHost. Cela peut se produire si vous avez récemment modifié votre enregistrement DNS. Si c'est le cas, merci dattendre quelques heures quil se propage. Si le problème persiste, envisager dajouter {domain:s} au fichier /etc/hosts. (Si vous savez ce que vous faites, utilisez --no-checks pour désactiver ces vérifications.)", "certmanager_domain_not_resolved_locally": "Le domaine {domain:s} ne peut être résolu depuis votre serveur YunoHost. Cela peut se produire si vous avez récemment modifié votre enregistrement DNS. Si c'est le cas, merci dattendre quelques heures quil se propage. Si le problème persiste, envisager dajouter {domain:s} au fichier /etc/hosts. (Si vous savez ce que vous faites, utilisez --no-checks pour désactiver ces vérifications.)",
"certmanager_http_check_timeout": "Expiration du délai lorsque le serveur a essayé de se contacter lui-même via HTTP en utilisant l'adresse IP public {ip:s} du domaine {domain:s}. Vous rencontrez peut-être un problème dhairpinning ou alors le pare-feu/routeur en amont de votre serveur est mal configuré.", "certmanager_http_check_timeout": "Expiration du délai lorsque le serveur a essayé de se contacter lui-même via HTTP en utilisant l'adresse IP public {ip:s} du domaine {domain:s}. Vous rencontrez peut-être un problème dhairpinning ou alors le pare-feu/routeur en amont de votre serveur est mal configuré.",
"certmanager_couldnt_fetch_intermediate_cert": "Expiration du délai lors de la tentative de récupération du certificat intermédiaire depuis Lets Encrypt. Linstallation ou le renouvellement du certificat a été annulé. Veuillez réessayer plus tard.", "certmanager_couldnt_fetch_intermediate_cert": "Expiration du délai lors de la tentative de récupération du certificat intermédiaire depuis Lets Encrypt. Linstallation ou le renouvellement du certificat a été annulé. Veuillez réessayer plus tard.",
"appslist_retrieve_bad_format": "Impossible de lire la liste des applications extraites {appslist: s}", "appslist_retrieve_bad_format": "Impossible de lire la liste des applications extraites '{appslist: s}'",
"domain_hostname_failed": "Échec de lutilisation dun nouveau nom dhôte. Cela pourrait causer des soucis plus tard (peut-être que ça nen causera pas).", "domain_hostname_failed": "Échec de lutilisation dun nouveau nom dhôte. Cela pourrait causer des soucis plus tard (peut-être que ça nen causera pas).",
"yunohost_ca_creation_success": "Lautorité de certification locale créée.", "yunohost_ca_creation_success": "Lautorité de certification locale créée.",
"appslist_name_already_tracked": "Il y a déjà une liste dapplications enregistrée avec le nom {name:s} existe déjà.", "appslist_name_already_tracked": "Une liste d'applications enregistrées portant le nom {name:s} existe déjà.",
"appslist_url_already_tracked": "Il y a déjà une liste dapplications enregistrée avec lURL {url:s}.", "appslist_url_already_tracked": "Il y a déjà une liste dapplications enregistrée avec lURL {url:s}.",
"appslist_migrating": "Migration de la liste dapplications {appslist:s} …", "appslist_migrating": "Migration de la liste dapplications '{appslist:s}' …",
"appslist_could_not_migrate": "Impossible de migrer la liste {appslist:s} ! Impossible dexploiter lURL. Lancienne tâche programmée a été conservée dans {bkp_file:s}.", "appslist_could_not_migrate": "Impossible de migrer la liste '{appslist:s}' ! Impossible dexploiter lURL. Lancienne tâche programmée a été conservée dans {bkp_file:s}.",
"appslist_corrupted_json": "Impossible de charger la liste dapplications. Il semble que {filename:s} soit endommager.", "appslist_corrupted_json": "Impossible de charger la liste dapplications. Il semble que {filename:s} soit endommager.",
"app_already_installed_cant_change_url": "Cette application est déjà installée. LURL ne peut pas être changé simplement par cette fonction. Regardez si cela est disponible avec `app changeurl`.", "app_already_installed_cant_change_url": "Cette application est déjà installée. LURL ne peut pas être changé simplement par cette fonction. Regardez si cela est disponible avec `app changeurl`.",
"app_change_no_change_url_script": "Lapplication {app_name:s} ne prend pas encore en charge le changement dURL, vous pourriez avoir besoin de la mettre à jour.", "app_change_no_change_url_script": "Lapplication {app_name:s} ne prend pas encore en charge le changement dURL, vous pourriez avoir besoin de la mettre à jour.",
@ -320,7 +320,7 @@
"backup_archive_system_part_not_available": "La partie '{part:s}' du système nest pas disponible dans cette sauvegarde", "backup_archive_system_part_not_available": "La partie '{part:s}' du système nest pas disponible dans cette sauvegarde",
"backup_archive_mount_failed": "Le montage de larchive de sauvegarde a échoué", "backup_archive_mount_failed": "Le montage de larchive de sauvegarde a échoué",
"backup_archive_writing_error": "Impossible d'ajouter des fichiers '{source:s}' (nommés dans l'archive : '{dest:s}') à sauvegarder dans l'archive compressée '{archive:s}'", "backup_archive_writing_error": "Impossible d'ajouter des fichiers '{source:s}' (nommés dans l'archive : '{dest:s}') à sauvegarder dans l'archive compressée '{archive:s}'",
"backup_ask_for_copying_if_needed": "Certains fichiers nont pas pu être préparés pour être sauvegardés en utilisant la méthode qui évite temporairement de gaspiller de lespace sur le système. Pour réaliser la sauvegarde, {size:s} Mo doivent être temporairement utilisés. Acceptez-vous ?", "backup_ask_for_copying_if_needed": "Voulez-vous effectuer la sauvegarde en utilisant {taille:s} temporairement? (Cette méthode est utilisée car certains fichiers n'ont pas pu être préparés avec une méthode plus efficace.)",
"backup_borg_not_implemented": "La méthode de sauvegarde Borg nest pas encore implémentée", "backup_borg_not_implemented": "La méthode de sauvegarde Borg nest pas encore implémentée",
"backup_cant_mount_uncompress_archive": "Impossible de monter en lecture seule le dossier de larchive décompressée", "backup_cant_mount_uncompress_archive": "Impossible de monter en lecture seule le dossier de larchive décompressée",
"backup_copying_to_organize_the_archive": "Copie de {size:s} Mo pour organiser larchive", "backup_copying_to_organize_the_archive": "Copie de {size:s} Mo pour organiser larchive",
@ -350,7 +350,7 @@
"domain_dyndns_dynette_is_unreachable": "Impossible de contacter la dynette YunoHost. Soit YunoHost nest pas correctement connecté à internet, soit le serveur de dynette est en panne. Erreur : {error}", "domain_dyndns_dynette_is_unreachable": "Impossible de contacter la dynette YunoHost. Soit YunoHost nest pas correctement connecté à internet, soit le serveur de dynette est en panne. Erreur : {error}",
"migrations_backward": "Migration en arrière.", "migrations_backward": "Migration en arrière.",
"migrations_bad_value_for_target": "Nombre invalide pour le paramètre target, les numéros de migration sont 0 ou {}", "migrations_bad_value_for_target": "Nombre invalide pour le paramètre target, les numéros de migration sont 0 ou {}",
"migrations_cant_reach_migration_file": "Impossible d'accéder aux fichiers de migration sur le chemin% s", "migrations_cant_reach_migration_file": "Impossible d'accéder aux fichiers de migration via le chemin '%s'",
"migrations_current_target": "La cible de migration est {}", "migrations_current_target": "La cible de migration est {}",
"migrations_error_failed_to_load_migration": "ERREUR : échec du chargement de migration {number} {name}", "migrations_error_failed_to_load_migration": "ERREUR : échec du chargement de migration {number} {name}",
"migrations_forward": "Migration en avant", "migrations_forward": "Migration en avant",
@ -368,9 +368,9 @@
"ask_path": "Chemin", "ask_path": "Chemin",
"dyndns_could_not_check_provide": "Impossible de vérifier si {provider:s} peut fournir {domain:s}.", "dyndns_could_not_check_provide": "Impossible de vérifier si {provider:s} peut fournir {domain:s}.",
"dyndns_domain_not_provided": "Le fournisseur DynDNS {provider:s} ne peut pas fournir le domaine {domain:s}.", "dyndns_domain_not_provided": "Le fournisseur DynDNS {provider:s} ne peut pas fournir le domaine {domain:s}.",
"app_make_default_location_already_used": "Impossible de configurer lapplication '{app}' par défaut pour le domaine {domain} car il est déjà utilisé par l'application '{other_app}'", "app_make_default_location_already_used": "Impossible de configurer lapplication '{app}' par défaut pour le domaine '{domain}' car il est déjà utilisé par l'application '{other_app}'",
"app_upgrade_app_name": "Mise à jour de lapplication {app} …", "app_upgrade_app_name": "Mise à jour de lapplication {app} …",
"backup_output_symlink_dir_broken": "Vous avez un lien symbolique cassé à la place de votre dossier darchives « {path:s} ». Vous pourriez avoir une configuration personnalisée pour sauvegarder vos données sur un autre système de fichiers, dans ce cas vous avez probablement oublié de monter ou de connecter votre disque dur ou votre clé USB.", "backup_output_symlink_dir_broken": "Votre répertoire d'archivage '{path:s}' est un lien symbolique brisé. Peut-être avez-vous oublié de re/monter ou de brancher le support de stockage sur lequel il pointe.",
"migrate_tsig_end": "La migration à HMAC-SHA-512 est terminée", "migrate_tsig_end": "La migration à HMAC-SHA-512 est terminée",
"migrate_tsig_failed": "La migration du domaine DynDNS {domain} à hmac-sha512 a échoué. Annulation des modifications. Erreur : {error_code} - {error}", "migrate_tsig_failed": "La migration du domaine DynDNS {domain} à hmac-sha512 a échoué. Annulation des modifications. Erreur : {error_code} - {error}",
"migrate_tsig_start": "Lalgorithme de génération des clefs nest pas suffisamment sécurisé pour la signature TSIG du domaine '{domain}', lancement de la migration vers HMAC-SHA-512 qui est plus sécurisé", "migrate_tsig_start": "Lalgorithme de génération des clefs nest pas suffisamment sécurisé pour la signature TSIG du domaine '{domain}', lancement de la migration vers HMAC-SHA-512 qui est plus sécurisé",
@ -473,7 +473,7 @@
"good_practices_about_admin_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe dadministration. Le mot de passe doit comporter au moins 8 caractères bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).", "good_practices_about_admin_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe dadministration. Le mot de passe doit comporter au moins 8 caractères bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).",
"good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe utilisateur. Le mot de passe doit comporter au moins 8 caractères - bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères tels que : majuscules, minuscules, chiffres et caractères spéciaux.", "good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe utilisateur. Le mot de passe doit comporter au moins 8 caractères - bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères tels que : majuscules, minuscules, chiffres et caractères spéciaux.",
"migration_description_0006_sync_admin_and_root_passwords": "Synchroniser les mots de passe admin et root", "migration_description_0006_sync_admin_and_root_passwords": "Synchroniser les mots de passe admin et root",
"migration_0006_disclaimer": "YunoHost sattendra désormais à ce que les mots de passe admin et root soient synchronisés. En exécutant cette migration, votre mot de passe root sera remplacé par le mot de passe administrateur.", "migration_0006_disclaimer": "YunoHost s'attend maintenant à ce que les mots de passe administrateur et racine soient synchronisés. Cette migration remplace votre mot de passe root par le mot de passe administrateur.",
"migration_0006_done": "Votre mot de passe root a été remplacé par celui de votre adminitrateur.", "migration_0006_done": "Votre mot de passe root a été remplacé par celui de votre adminitrateur.",
"password_listed": "Ce mot de passe est l'un des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose d'un peu plus singulier.", "password_listed": "Ce mot de passe est l'un des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose d'un peu plus singulier.",
"password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères", "password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères",
@ -485,7 +485,7 @@
"app_not_upgraded": "Lapplication {failed_app} na pas été mise à jour et par conséquence les applications suivantes nont pas été mises à jour : {apps}", "app_not_upgraded": "Lapplication {failed_app} na pas été mise à jour et par conséquence les applications suivantes nont pas été mises à jour : {apps}",
"app_start_install": "Installation de l'application {app} …", "app_start_install": "Installation de l'application {app} …",
"app_start_remove": "Suppression de l'application {app} …", "app_start_remove": "Suppression de l'application {app} …",
"app_start_backup": "Collecte des fichiers devant être sauvegardés pour {app} …", "app_start_backup": "Collecte des fichiers devant être sauvegardés pour l'application {app} …",
"app_start_restore": "Restauration de l'application {app} …", "app_start_restore": "Restauration de l'application {app} …",
"app_upgrade_several_apps": "Les applications suivantes seront mises à jour : {apps}", "app_upgrade_several_apps": "Les applications suivantes seront mises à jour : {apps}",
"ask_new_domain": "Nouveau domaine", "ask_new_domain": "Nouveau domaine",
@ -493,8 +493,8 @@
"backup_actually_backuping": "Création d'une archive de sauvegarde à partir des fichiers collectés …", "backup_actually_backuping": "Création d'une archive de sauvegarde à partir des fichiers collectés …",
"backup_mount_archive_for_restore": "Préparation de l'archive pour restauration …", "backup_mount_archive_for_restore": "Préparation de l'archive pour restauration …",
"confirm_app_install_warning": "Avertissement : cette application peut fonctionner mais n'est pas bien intégrée dans YunoHost. Certaines fonctionnalités telles que l'authentification unique et la sauvegarde/restauration peuvent ne pas être disponibles. L'installer quand même ? [{answers:s}] ", "confirm_app_install_warning": "Avertissement : cette application peut fonctionner mais n'est pas bien intégrée dans YunoHost. Certaines fonctionnalités telles que l'authentification unique et la sauvegarde/restauration peuvent ne pas être disponibles. L'installer quand même ? [{answers:s}] ",
"confirm_app_install_danger": "AVERTISSEMENT ! Cette application est encore expérimentale (explicitement, elle ne fonctionne pas) et risque de casser votre système ! Vous ne devriez probablement PAS l'installer sans savoir ce que vous faites. Êtes-vous prêt à prendre ce risque ? [{answers:s}] ", "confirm_app_install_danger": "DANGER! Cette application est connue pour être encore expérimentale (si elle ne fonctionne pas explicitement)! Vous ne devriez probablement PAS l'installer à moins de savoir ce que vous faites. AUCUN SUPPORT ne sera fourni si cette application ne fonctionne pas ou casse votre système ... Si vous êtes prêt à prendre ce risque de toute façon, tapez '{answers: s}'",
"confirm_app_install_thirdparty": "AVERTISSEMENT ! L'installation d'applications tierces peut compromettre l'intégrité et la sécurité de votre système. Vous ne devriez probablement PAS l'installer si vous ne savez pas ce que vous faites. Êtes-vous prêt à prendre ce risque ? [{answers:s}] ", "confirm_app_install_thirdparty": "DANGER! Cette application ne fait pas partie du catalogue d'applications de Yunohost. L'installation d'applications tierces peut compromettre l'intégrité et la sécurité de votre système. Vous ne devriez probablement PAS l'installer à moins de savoir ce que vous faites. AUCUN SUPPORT ne sera fourni si cette application ne fonctionne pas ou casse votre système ... Si vous êtes prêt à prendre ce risque de toute façon, tapez '{answers:s}'",
"dpkg_is_broken": "Vous ne pouvez pas faire ça maintenant car dpkg/apt (le gestionnaire de paquets du système) semble avoir laissé des choses non configurées. Vous pouvez essayer de résoudre ce problème en vous connectant via SSH et en exécutant `sudo dpkg --configure -a'.", "dpkg_is_broken": "Vous ne pouvez pas faire ça maintenant car dpkg/apt (le gestionnaire de paquets du système) semble avoir laissé des choses non configurées. Vous pouvez essayer de résoudre ce problème en vous connectant via SSH et en exécutant `sudo dpkg --configure -a'.",
"dyndns_could_not_check_available": "Impossible de vérifier si {domain:s} est disponible chez {provider:s}.", "dyndns_could_not_check_available": "Impossible de vérifier si {domain:s} est disponible chez {provider:s}.",
"file_does_not_exist": "Le fichier dont le chemin est {path:s} n'existe pas.", "file_does_not_exist": "Le fichier dont le chemin est {path:s} n'existe pas.",
@ -504,14 +504,14 @@
"hook_json_return_error": "Échec de la lecture au retour du script {path:s}. Erreur : {msg:s}. Contenu brut : {raw_content}", "hook_json_return_error": "Échec de la lecture au retour du script {path:s}. Erreur : {msg:s}. Contenu brut : {raw_content}",
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "La configuration SSH sera gérée par YunoHost (étape 1, automatique)", "migration_description_0007_ssh_conf_managed_by_yunohost_step1": "La configuration SSH sera gérée par YunoHost (étape 1, automatique)",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "La configuration SSH sera gérée par YunoHost (étape 2, manuelle)", "migration_description_0008_ssh_conf_managed_by_yunohost_step2": "La configuration SSH sera gérée par YunoHost (étape 2, manuelle)",
"migration_0007_cancelled": "YunoHost n'a pas réussi à améliorer la façon dont est gérée votre configuration SSH.", "migration_0007_cancelled": "Impossible d'améliorer la gestion de votre configuration SSH.",
"migration_0007_cannot_restart": "SSH ne peut pas être redémarré après avoir essayé d'annuler la migration numéro 6.", "migration_0007_cannot_restart": "SSH ne peut pas être redémarré après avoir essayé d'annuler la migration numéro 6.",
"migration_0008_general_disclaimer": "Pour améliorer la sécurité de votre serveur, il est recommandé de laisser YunoHost gérer la configuration SSH. Votre configuration SSH actuelle diffère de la configuration recommandée. Si vous laissez YunoHost la reconfigurer, la façon dont vous vous connectez à votre serveur via SSH changera comme suit :", "migration_0008_general_disclaimer": "Pour améliorer la sécurité de votre serveur, il est recommandé de laisser YunoHost gérer la configuration SSH. Votre configuration SSH actuelle diffère de la configuration recommandée. Si vous laissez YunoHost la reconfigurer, la façon dont vous vous connectez à votre serveur via SSH changera comme suit :",
"migration_0008_port": "- Vous devrez vous connecter en utilisant le port 22 au lieu de votre actuel port SSH personnalisé. N'hésitez pas à le reconfigurer ;", "migration_0008_port": "- Vous devrez vous connecter en utilisant le port 22 au lieu de votre actuel port SSH personnalisé. N'hésitez pas à le reconfigurer ;",
"migration_0008_root": "- Vous ne pourrez pas vous connecter en tant que root via SSH. Au lieu de cela, vous devrez utiliser l'utilisateur admin ;", "migration_0008_root": "- Vous ne pourrez pas vous connecter en tant que root via SSH. Au lieu de cela, vous devrez utiliser l'utilisateur admin ;",
"migration_0008_dsa": "- La clé DSA sera désactivée. Par conséquent, il se peut que vous ayez besoin d'invalider un avertissement effrayant de votre client SSH afin de revérifier l'empreinte de votre serveur ;", "migration_0008_dsa": "- La clé DSA sera désactivée. Par conséquent, il se peut que vous ayez besoin d'invalider un avertissement effrayant de votre client SSH afin de revérifier l'empreinte de votre serveur ;",
"migration_0008_warning": "Si vous comprenez ces avertissements et que vous acceptez de laisser YunoHost remplacer votre configuration actuelle, exécutez la migration. Sinon, vous pouvez également passer la migration, bien que cela ne soit pas recommandé.", "migration_0008_warning": "Si vous comprenez ces avertissements et souhaitez que YunoHost écrase votre configuration actuelle, exécutez la migration. Sinon, vous pouvez également ignorer la migration, bien que cela ne soit pas recommandé.",
"migration_0008_no_warning": "Aucun risque majeur n'a été identifié concernant l'écrasement de votre configuration SSH - mais nous ne pouvons pas en être absolument sûrs ;) ! Si vous acceptez de laisser YunoHost remplacer votre configuration actuelle, exécutez la migration. Sinon, vous pouvez également passer la migration, bien que cela ne soit pas recommandé.", "migration_0008_no_warning": "Remplacer votre configuration SSH devrait être sûr, bien que cela ne puisse être promis! Exécutez la migration pour la remplacer. Sinon, vous pouvez également ignorer la migration, bien que cela ne soit pas recommandé.",
"migrations_success": "Migration {number} {name} réussie !", "migrations_success": "Migration {number} {name} réussie !",
"pattern_password_app": "Désolé, les mots de passe ne doivent pas contenir les caractères suivants : {forbidden_chars}", "pattern_password_app": "Désolé, les mots de passe ne doivent pas contenir les caractères suivants : {forbidden_chars}",
"root_password_replaced_by_admin_password": "Votre mot de passe root a été remplacé par votre mot de passe administrateur.", "root_password_replaced_by_admin_password": "Votre mot de passe root a été remplacé par votre mot de passe administrateur.",
@ -523,7 +523,7 @@
"service_reload_or_restart_failed": "Impossible de recharger ou de redémarrer le service '{service:s}'\n\nJournaux historisés récents de ce service : {logs:s}", "service_reload_or_restart_failed": "Impossible de recharger ou de redémarrer le service '{service:s}'\n\nJournaux historisés récents de ce service : {logs:s}",
"service_reloaded_or_restarted": "Le service '{service:s}' a été rechargé ou redémarré", "service_reloaded_or_restarted": "Le service '{service:s}' a été rechargé ou redémarré",
"this_action_broke_dpkg": "Cette action a laissé des paquets non configurés par dpkg/apt (les gestionnaires de paquets système). Vous pouvez essayer de résoudre ce problème en vous connectant via SSH et en exécutant `sudo dpkg --configure -a`.", "this_action_broke_dpkg": "Cette action a laissé des paquets non configurés par dpkg/apt (les gestionnaires de paquets système). Vous pouvez essayer de résoudre ce problème en vous connectant via SSH et en exécutant `sudo dpkg --configure -a`.",
"app_action_cannot_be_ran_because_required_services_down": "Cette application requiert certains services qui sont actuellement arrêtés. Avant de continuer, vous devriez essayer de redémarrer les services suivants (et éventuellement rechercher pourquoi ils sont arrêtés) : {services}", "app_action_cannot_be_ran_because_required_services_down": "Ces services requis doivent être en cours d'exécution pour exécuter cette action: {services}. Essayez de les redémarrer pour continuer (et éventuellement rechercher pourquoi ils sont en panne).",
"admin_password_too_long": "Veuillez choisir un mot de passe de moins de 127 caractères", "admin_password_too_long": "Veuillez choisir un mot de passe de moins de 127 caractères",
"log_regen_conf": "Régénérer les configurations du système '{}'", "log_regen_conf": "Régénérer les configurations du système '{}'",
"migration_0009_not_needed": "Cette migration semble avoir déjà été jouée ? On l'ignore.", "migration_0009_not_needed": "Cette migration semble avoir déjà été jouée ? On l'ignore.",
@ -558,8 +558,8 @@
"tools_upgrade_special_packages_completed": "La mise à jour des paquets de YunoHost est finie!\nPressez [Entrée] pour revenir à la ligne de commande", "tools_upgrade_special_packages_completed": "La mise à jour des paquets de YunoHost est finie!\nPressez [Entrée] pour revenir à la ligne de commande",
"updating_app_lists": "Récupération des mises à jour des applications disponibles…", "updating_app_lists": "Récupération des mises à jour des applications disponibles…",
"dpkg_lock_not_available": "Cette commande ne peut être exécutée actuellement car un autre programme semble utiliser le verrou de dpkg (gestionnaire de paquets)", "dpkg_lock_not_available": "Cette commande ne peut être exécutée actuellement car un autre programme semble utiliser le verrou de dpkg (gestionnaire de paquets)",
"tools_upgrade_cant_unhold_critical_packages": "Impossible de dé-marquer les paquets critiques …", "tools_upgrade_cant_unhold_critical_packages": "Impossible de conserver les paquets critiques…",
"tools_upgrade_special_packages_explanation": "Cette opération prendra fin mais la mise à jour spécifique continuera en arrière-plan. Veuillez ne pas lancer d'autre action sur votre serveur dans les 10 prochaines minutes (en fonction de la vitesse de votre matériel). Une fois que c'est fait, vous devrez peut-être vous reconnecter sur le panel d'administration web. Le journal de la mise à jour sera disponible dans Outils > Log (dans le panel d'administration web) ou dans la liste des journaux YunoHost (en ligne de commande).", "tools_upgrade_special_packages_explanation": "Cette action se terminera, mais la mise à niveau spéciale réelle continuera en arrière-plan. Veuillez ne pas lancer dautres actions sur votre serveur au cours des 10 prochaines minutes (en fonction de la vitesse du matériel). Une fois cela fait, vous devrez peut-être vous reconnecter à la page Webadmin. Le journal de mise à niveau sera disponible dans Outils → Journal (sur la page Webadmin) ou dans la \"liste des journaux yunohost\" (à partir de la ligne de commande).",
"update_apt_cache_failed": "Impossible de mettre à jour le cache APT (gestionnaire de paquets Debian). Voici un extrait du fichier sources.list qui pourrait vous aider à identifier les lignes problématiques :\n{sourceslist}", "update_apt_cache_failed": "Impossible de mettre à jour le cache APT (gestionnaire de paquets Debian). Voici un extrait du fichier sources.list qui pourrait vous aider à identifier les lignes problématiques :\n{sourceslist}",
"update_apt_cache_warning": "Des erreurs se sont produites lors de la mise à jour du cache APT (gestionnaire de paquets Debian). Voici un extrait des lignes du fichier sources.list qui pourrait vous aider à identifier les lignes problématiques :\n{sourceslist}", "update_apt_cache_warning": "Des erreurs se sont produites lors de la mise à jour du cache APT (gestionnaire de paquets Debian). Voici un extrait des lignes du fichier sources.list qui pourrait vous aider à identifier les lignes problématiques :\n{sourceslist}",
"apps_permission_not_found": "Aucune permission trouvée pour les applications installées", "apps_permission_not_found": "Aucune permission trouvée pour les applications installées",
@ -573,12 +573,12 @@
"group_info_failed": "L'information sur le groupe a échoué", "group_info_failed": "L'information sur le groupe a échoué",
"group_unknown": "Le groupe {group:s} est inconnu", "group_unknown": "Le groupe {group:s} est inconnu",
"group_updated": "Le groupe '{group}' a été mis à jour", "group_updated": "Le groupe '{group}' a été mis à jour",
"group_update_failed": "La mise à jour du groupe '{group}' a échoué", "group_update_failed": "La mise à jour du groupe '{group}' a échoué : {error}",
"group_already_allowed": "Le groupe '{group:s}' a déjà la permission '{permission:s}' activée pour l'application '{app:s}'", "group_already_allowed": "Le groupe '{group:s}' a déjà la permission '{permission:s}' activée pour l'application '{app:s}'",
"group_already_disallowed": "Le groupe '{group:s}' a déjà la permission '{permission:s}' désactivée pour l'application '{app:s}'", "group_already_disallowed": "Le groupe '{group:s}' a déjà la permission '{permission:s}' désactivée pour l'application '{app:s}'",
"group_name_already_exist": "Le groupe {name:s} existe déjà", "group_name_already_exist": "Le groupe {name:s} existe déjà",
"group_creation_failed": "Échec de la création du groupe '{group}'", "group_creation_failed": "Échec de la création du groupe '{group}': {error}",
"group_deletion_failed": "Échec de la suppression du groupe '{group}'", "group_deletion_failed": "Échec de la suppression du groupe '{group}': {error}",
"edit_permission_with_group_all_users_not_allowed": "Vous n'êtes pas autorisé à modifier les permissions pour le groupe 'all_users', utilisez 'yunohost user permission clear APP' ou 'yunohost user permission add APP -u USER' à la place.", "edit_permission_with_group_all_users_not_allowed": "Vous n'êtes pas autorisé à modifier les permissions pour le groupe 'all_users', utilisez 'yunohost user permission clear APP' ou 'yunohost user permission add APP -u USER' à la place.",
"log_permission_add": "Ajouter l'autorisation '{}' pour l'application '{}'", "log_permission_add": "Ajouter l'autorisation '{}' pour l'application '{}'",
"log_permission_remove": "Supprimer l'autorisation '{}'", "log_permission_remove": "Supprimer l'autorisation '{}'",
@ -591,49 +591,78 @@
"mailbox_disabled": "La boîte aux lettres est désactivée pour l'utilisateur {user:s}", "mailbox_disabled": "La boîte aux lettres est désactivée pour l'utilisateur {user:s}",
"app_action_broke_system": "Cette action semble avoir cassé des services important : {services}", "app_action_broke_system": "Cette action semble avoir cassé des services important : {services}",
"apps_already_up_to_date": "Toutes les applications sont déjà à jour", "apps_already_up_to_date": "Toutes les applications sont déjà à jour",
"app_upgrade_stopped": "La mise à jour de toutes les applications a été arrêtée afin déviter déventuels dommages dus à léchec de la mise à jour de lapplication précédente", "app_upgrade_stopped": "La mise à niveau de toutes les applications s'est arrêtée pour éviter tout dommage, car une application n'a pas pu être mise à niveau.",
"migration_0011_create_group": "Créer un groupe pour chaque utilisateur…", "migration_0011_create_group": "Créer un groupe pour chaque utilisateur…",
"migration_0011_done": "Migration réussie. Vous êtes maintenant en mesure de gérer des groupes d'utilisateurs.", "migration_0011_done": "Migration terminée. Vous êtes maintenant en mesure de gérer des groupes d'utilisateurs.",
"migrations_must_provide_explicit_targets": "Vous devez fournir des cibles explicites lorsque vous utilisez '--skip' ou '--force-rerun'", "migrations_must_provide_explicit_targets": "Vous devez fournir des cibles explicites lorsque vous utilisez '--skip' ou '--force-rerun'",
"migrations_no_such_migration": "Il n'y a pas de migration appelée {id}", "migrations_no_such_migration": "Il n'y a pas de migration appelée '{id}'",
"migrations_pending_cant_rerun": "Ces migrations étant toujours en attente, vous ne pouvez pas les exécuter à nouveau: {ids}", "migrations_pending_cant_rerun": "Ces migrations étant toujours en attente, vous ne pouvez pas les exécuter à nouveau: {ids}",
"migration_description_0012_postgresql_password_to_md5_authentication": "Forcer l'authentification PostgreSQL à utiliser MD5 pour les connexions locales", "migration_description_0012_postgresql_password_to_md5_authentication": "Forcer l'authentification PostgreSQL à utiliser MD5 pour les connexions locales",
"migrations_exclusive_options": "'auto', '--skip' et '--force-rerun' sont des options mutuellement exclusives.", "migrations_exclusive_options": "'auto', '--skip' et '--force-rerun' sont des options mutuellement exclusives.",
"migrations_not_pending_cant_skip": "Ces migrations ne sont pas en attente et ne peuvent donc pas être ignorées: {ids}", "migrations_not_pending_cant_skip": "Ces migrations ne sont pas en attente et ne peuvent donc pas être ignorées: {ids}",
"migration_0011_can_not_backup_before_migration": "Impossible de sauvegarder le système avant la migration. Erreur: {error: s}", "migration_0011_can_not_backup_before_migration": "La sauvegarde du système n'a pas pu être terminée avant l'échec de la migration. Erreur: {erreur:s}",
"migration_0011_migrate_permission": "Migration des autorisations des paramètres des applications vers LDAP…", "migration_0011_migrate_permission": "Migration des autorisations des paramètres des applications vers LDAP…",
"migration_0011_migration_failed_trying_to_rollback": "La migration a échoué… essayait de restauration du système.", "migration_0011_migration_failed_trying_to_rollback": "Impossible de migrer… en essayant de restaurer le système.",
"migration_0011_rollback_success": "Système restauré.", "migration_0011_rollback_success": "Système restauré.",
"migration_0011_update_LDAP_database": "Mise à jour de la base de données LDAP…", "migration_0011_update_LDAP_database": "Mise à jour de la base de données LDAP…",
"system_groupname_exists": "Le nom de groupe existe déjà dans le groupe du systèmes", "system_groupname_exists": "Le nom de groupe existe déjà dans le groupe du systèmes",
"tools_update_failed_to_app_fetchlist": "Impossible de mettre à jour les applications de YunoHost car: {error}", "tools_update_failed_to_app_fetchlist": "Impossible de mettre à jour les listes d'applications de YunoHost car: {error}",
"user_already_in_group": "L'utilisateur '{user:}' est déjà dans le groupe '{group: s}'", "user_already_in_group": "L'utilisateur '{user:}' est déjà dans le groupe '{group: s}'",
"user_not_in_group": "L'utilisateur '{user: s}' ne fait pas partie du groupe {group: s}", "user_not_in_group": "L'utilisateur '{user: s}' ne fait pas partie du groupe {group: s}",
"migration_0011_backup_before_migration": "Création d'une sauvegarde des paramètres de la base de données LDAP et des applications avant la migration.", "migration_0011_backup_before_migration": "Création d'une sauvegarde des paramètres de la base de données LDAP et des applications avant la migration.",
"permission_not_found": "Autorisation '{permission: s}' non trouvée pour l'application '{app: s}'", "permission_not_found": "Autorisation '{permission:s}' introuvable",
"permission_name_not_valid": "Choisissez un nom d'autorisation autorisé pour '{permission: s}'", "permission_name_not_valid": "Choisissez un nom d'autorisation autorisé pour '{permission: s}'",
"permission_update_failed": "Impossible de mettre à jour la permission", "permission_update_failed": "Impossible de mettre à jour la permission '{permission}': {error}",
"permission_generated": "Base de données des autorisations mise à jour", "permission_generated": "Base de données des autorisations mise à jour",
"permission_updated": "Permission '{permission: s}' pour l'application '{app: s}' mise à jour", "permission_updated": "Permission '{permission:s}' mise à jour",
"permission_update_nothing_to_do": "Aucune autorisation pour mettre à jour", "permission_update_nothing_to_do": "Aucune autorisation pour mettre à jour",
"remove_main_permission_not_allowed": "Supprimer l'autorisation principale n'est pas autorisé", "remove_main_permission_not_allowed": "Supprimer l'autorisation principale n'est pas autorisé",
"dyndns_provider_unreachable": "Impossible datteindre le fournisseur Dyndns {provider}: votre YunoHost nest pas correctement connecté à Internet ou le serveur Dynette est en panne.", "dyndns_provider_unreachable": "Impossible datteindre le fournisseur Dyndns {provider}: votre YunoHost nest pas correctement connecté à Internet ou le serveur Dynette est en panne.",
"migration_0011_update_LDAP_schema": "Mise à jour du schéma LDAP…", "migration_0011_update_LDAP_schema": "Mise à jour du schéma LDAP…",
"migrations_already_ran": "Ces migrations sont déjà effectuées: {ids}", "migrations_already_ran": "Ces migrations sont déjà effectuées: {ids}",
"migrations_dependencies_not_satisfied": "Impossible d'exécuter la migration {id} car vous devez d'abord exécuter ces migrations: {dependencies_id}", "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_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", "migrations_success_forward": "Migration {id} terminée",
"need_define_permission_before": "Redéfinissez l'autorisation à l'aide de 'yunohost user permission add -u USER' avant de supprimer un groupe autorisé", "need_define_permission_before": "Redéfinissez l'autorisation à l'aide de 'yunohost user permission add -u USER' avant de supprimer un groupe autorisé",
"operation_interrupted": "L'opération a été interrompue manuellement", "operation_interrupted": "L'opération a-t-elle été interrompue manuellement ?",
"permission_already_clear": "L'autorisation '{permission: s}' est déjà vide pour l'application {app: s}", "permission_already_clear": "L'autorisation '{permission: s}' est déjà vide pour l'application {app: s}",
"permission_already_exist": "L'autorisation '{permission: s}' pour l'application {app: s} existe déjà", "permission_already_exist": "L'autorisation '{permission}' existe déjà",
"permission_created": "Permission '{permission: s}' pour l'application {app: s} créée", "permission_created": "Permission '{permission:s}' créée",
"permission_creation_failed": "Impossible d'accorder la permission", "permission_creation_failed": "Impossible de créer l'autorisation '{permission}': {erreur}",
"permission_deleted": "Permission '{permission: s}' pour app {app: s} supprimée", "permission_deleted": "Permission '{permission:s}' supprimée",
"permission_deletion_failed": "Autorisation manquante '{permission: s}' pour supprimer l'application '{app: s}'", "permission_deletion_failed": "Impossible de supprimer la permission '{permission}': {error}",
"remove_user_of_group_not_allowed": "Vous n'êtes pas autorisé à supprimer l'utilisateur '{utilisateur: s}' dans le groupe '{groupe: s}'", "remove_user_of_group_not_allowed": "Vous n'êtes pas autorisé à supprimer l'utilisateur '{utilisateur: s}' dans le groupe '{groupe: s}'",
"migration_description_0011_setup_group_permission": "Configurer le groupe d'utilisateurs et configurer les autorisations pour les applications et les services", "migration_description_0011_setup_group_permission": "Configurer le groupe d'utilisateurs et configurer les autorisations pour les applications et les services",
"migration_0011_LDAP_config_dirty": "Il semble que vous ayez personnalisé votre configuration LDAP. Pour cette migration, la configuration LDAP doit être mise à jour.\nVous devez enregistrer votre configuration actuelle, réintialiser la configuration d'origine en exécutant 'yunohost tools regen-conf -f', puis réessayer la migration", "migration_0011_LDAP_config_dirty": "Il semble que vous ayez personnalisé votre configuration LDAP. Pour cette migration, la configuration LDAP doit être mise à jour.\nVous devez enregistrer votre configuration actuelle, réintialiser la configuration d'origine en exécutant 'yunohost tools regen-conf -f', puis réessayer la migration",
"migration_0011_LDAP_update_failed": "Impossible de mettre à jour LDAP. Erreur: {error: s}" "migration_0011_LDAP_update_failed": "Impossible de mettre à jour LDAP. Erreur: {error: s}",
"group_already_exist": "Le groupe {group} existe déjà",
"group_already_exist_on_system": "Le groupe {group} existe déjà dans les groupes système",
"group_cannot_be_edited": "Le groupe {group} ne peut pas être édité manuellement.",
"group_cannot_be_deleted": "Le groupe {group} ne peut pas être supprimé manuellement.",
"group_user_already_in_group": "L'utilisateur {user} est déjà dans le groupe {group}",
"group_user_not_in_group": "L'utilisateur {user} n'est pas dans le groupe {group}",
"log_permission_create": "Créer permission '{}'",
"log_permission_delete": "supprimer permission '{}'",
"log_permission_urls": "Mettre à jour les URL liées à la permission '{}'",
"log_user_group_create": "Créer '{}' groupe",
"log_user_permission_update": "Mise à jour des accès pour la permission '{}'",
"log_user_permission_reset": "Réinitialiser la permission '{}'",
"migration_0011_failed_to_remove_stale_object": "Impossible de supprimer un objet périmé {dn}: {error}",
"permission_already_allowed": "Le groupe '{group}' a déjà l'autorisation '{permission}' activée",
"permission_already_disallowed": "Le groupe '{group}' a déjà l'autorisation '{permission}' désactivé '",
"permission_cannot_remove_main": "Supprimer une autorisation principale n'est pas autorisé",
"user_already_exists": "L'utilisateur '{user}' existe déjà",
"app_full_domain_unavailable": "Désolé, cette application doit être installée sur un domaine qui lui est propre, mais d'autres applications sont déjà installées sur le domaine '{domain}'. Vous pouvez utiliser un sous-domaine dédié à cette application à la place.",
"group_cannot_edit_all_users": "Le groupe 'all_users' ne peut pas être édité manuellement. C'est un groupe spécial destiné à contenir tous les utilisateurs enregistrés dans YunoHost",
"group_cannot_edit_visitors": "Le groupe 'visiteurs' ne peut pas être édité manuellement. C'est un groupe spécial représentant les visiteurs anonymes",
"group_cannot_edit_primary_group": "Le groupe '{group}' ne peut pas être édité manuellement. C'est le groupe principal destiné à ne contenir qu'un utilisateur spécifique.",
"log_permission_url": "Mise à jour de l'URL associée à l'autorisation '{}'",
"migration_0011_slapd_config_will_be_overwritten": "Il semble que vous ayez modifié manuellement la configuration de slapd. Pour cette migration critique, YunoHost doit forcer la mise à jour de la configuration de slapd. Les fichiers originaux seront sauvegardés dans {conf_backup_folder}.",
"permission_already_up_to_date": "L'autorisation n'a pas été mise à jour car les demandes d'ajout/suppression correspondent déjà à l'état actuel.",
"permission_currently_allowed_for_visitors": "Cette autorisation est actuellement accordée aux visiteurs en plus d'autres groupes. Vous voudrez probablement supprimer l'autorisation \"visiteurs\" ou supprimer les autres groupes auxquels il est actuellement attribué.",
"permission_currently_allowed_for_all_users": "Cette autorisation est actuellement accordée à tous les utilisateurs en plus des autres groupes. Vous voudrez probablement soit supprimer l'autorisation 'all_users', soit supprimer les autres groupes auxquels il est actuellement autorisé.",
"app_install_failed": "Impossible d'installer {app}: {error}",
"app_install_script_failed": "Une erreur est survenue dans le script d'installation de l'application",
"permission_require_account": "Permission {permission} n'a de sens que pour les utilisateurs ayant un compte et ne peut donc pas être activé pour les visiteurs."
} }

View file

@ -72,7 +72,7 @@
"ldap_initialized": "LDAP inicializada com êxito", "ldap_initialized": "LDAP inicializada com êxito",
"license_undefined": "indefinido", "license_undefined": "indefinido",
"mail_alias_remove_failed": "Não foi possível remover a etiqueta de correio '{mail:s}'", "mail_alias_remove_failed": "Não foi possível remover a etiqueta de correio '{mail:s}'",
"mail_domain_unknown": "Domínio de endereço de correio desconhecido '{domain:s}'", "mail_domain_unknown": "Domínio de endereço de correio '{domain:s}' inválido. Por favor, usa um domínio administrado per esse servidor.",
"mail_forward_remove_failed": "Não foi possível remover o reencaminhamento de correio '{mail:s}'", "mail_forward_remove_failed": "Não foi possível remover o reencaminhamento de correio '{mail:s}'",
"main_domain_change_failed": "Incapaz alterar o domínio raiz", "main_domain_change_failed": "Incapaz alterar o domínio raiz",
"main_domain_changed": "Domínio raiz alterado com êxito", "main_domain_changed": "Domínio raiz alterado com êxito",

View file

@ -1 +1,3 @@
{} {
"password_too_simple_1": "Lösenordet måste bestå av minst åtta tecken"
}

View file

@ -41,7 +41,7 @@ from datetime import datetime
from moulinette import msignals, m18n, msettings from moulinette import msignals, m18n, msettings
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import read_json, read_toml from moulinette.utils.filesystem import read_json, read_toml, read_yaml, write_to_json
from yunohost.service import service_log, service_status, _run_service_command from yunohost.service import service_log, service_status, _run_service_command
from yunohost.utils import packages from yunohost.utils import packages
@ -427,23 +427,85 @@ def app_map(app=None, raw=False, user=None):
if 'path' not in app_settings: if 'path' not in app_settings:
# we assume that an app that doesn't have a path doesn't have an HTTP api # we assume that an app that doesn't have a path doesn't have an HTTP api
continue continue
# This 'no_sso' settings sound redundant to not having $path defined ....
# At least from what I can see, all apps using it don't have a path defined ...
if 'no_sso' in app_settings: # I don't think we need to check for the value here if 'no_sso' in app_settings: # I don't think we need to check for the value here
continue continue
if user and user not in permissions[app_id + ".main"]["corresponding_users"]: # Users must at least have access to the main permission to have access to extra permissions
if user:
if not app_id + ".main" in permissions:
logger.warning("Uhoh, no main permission was found for app %s ... sounds like an app was only partially removed due to another bug :/" % app_id)
continue
main_perm = permissions[app_id + ".main"]
if user not in main_perm["corresponding_users"] and "visitors" not in main_perm["allowed"]:
continue continue
domain = app_settings['domain'] domain = app_settings['domain']
path = app_settings['path'] path = app_settings['path'].rstrip('/')
label = app_settings['label']
def _sanitized_absolute_url(perm_url):
# Nominal case : url is relative to the app's path
if perm_url.startswith("/"):
perm_domain = domain
perm_path = path + perm_url.rstrip("/")
# Otherwise, the urls starts with a domain name, like domain.tld/foo/bar
# We want perm_domain = domain.tld and perm_path = "/foo/bar"
else:
perm_domain, perm_path = perm_url.split("/", 1)
perm_path = "/" + perm_path.rstrip("/")
return perm_domain, perm_path
this_app_perms = {p: i for p, i in permissions.items() if p.startswith(app_id + ".") and i["url"]}
for perm_name, perm_info in this_app_perms.items():
# If we're building the map for a specific user, check the user
# actually is allowed for this specific perm
if user and user not in perm_info["corresponding_users"] and "visitors" not in perm_info["allowed"]:
continue
if perm_info["url"].startswith("re:"):
# Here, we have an issue if the chosen url is a regex, because
# the url we want to add to the dict is going to be turned into
# a clickable link (or analyzed by other parts of yunohost
# code...). To put it otherwise : in the current code of ssowat,
# you can't give access a user to a regex.
#
# Instead, as drafted by Josue, we could rework the ssowat logic
# about how routes and their permissions are defined. So for example,
# have a dict of
# { "/route1": ["visitors", "user1", "user2", ...], # Public route
# "/route2_with_a_regex$": ["user1", "user2"], # Private route
# "/route3": None, # Skipped route idk
# }
# then each time a user try to request and url, we only keep the
# longest matching rule and check the user is allowed etc...
#
# The challenge with this is (beside actually implementing it)
# is that it creates a whole new mechanism that ultimately
# replace all the existing logic about
# protected/unprotected/skipped uris and regexes and we gotta
# handle / migrate all the legacy stuff somehow if we don't
# want to end up with a total mess in the future idk
logger.error("Permission %s can't be added to the SSOwat configuration because it doesn't support regexes so far..." % perm_name)
continue
perm_domain, perm_path = _sanitized_absolute_url(perm_info["url"])
if perm_name.endswith(".main"):
perm_label = label
else:
# e.g. if perm_name is wordpress.admin, we want "Blog (Admin)" (where Blog is the label of this app)
perm_label = "%s (%s)" % (label, perm_name.rsplit(".")[-1].replace("_", " ").title())
if raw: if raw:
if domain not in result: if domain not in result:
result[domain] = {} result[perm_domain] = {}
result[domain][path] = { result[perm_domain][perm_path] = {
'label': app_settings['label'], 'label': perm_label,
'id': app_settings['id'] 'id': app_id
} }
else: else:
result[domain + path] = app_settings['label'] result[perm_domain + perm_path] = perm_label
return result return result
@ -461,7 +523,6 @@ def app_change_url(operation_logger, app, domain, path):
""" """
from yunohost.hook import hook_exec, hook_callback from yunohost.hook import hook_exec, hook_callback
from yunohost.domain import _normalize_domain_path, _get_conflicting_apps from yunohost.domain import _normalize_domain_path, _get_conflicting_apps
from yunohost.permission import permission_urls
installed = _is_installed(app) installed = _is_installed(app)
if not installed: if not installed:
@ -551,7 +612,7 @@ def app_change_url(operation_logger, app, domain, path):
app_setting(app, 'domain', value=domain) app_setting(app, 'domain', value=domain)
app_setting(app, 'path', value=path) app_setting(app, 'path', value=path)
permission_urls(app+".main", add=[domain+path], remove=[old_domain+old_path], sync_perm=True) app_ssowatconf()
# avoid common mistakes # avoid common mistakes
if _run_service_command("reload", "nginx") is False: if _run_service_command("reload", "nginx") is False:
@ -763,7 +824,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback
from yunohost.log import OperationLogger from yunohost.log import OperationLogger
from yunohost.permission import user_permission_list, permission_create, permission_urls, permission_delete, permission_sync_to_user from yunohost.permission import user_permission_list, permission_create, permission_url, permission_delete, permission_sync_to_user, user_permission_update
# Fetch or extract sources # Fetch or extract sources
if not os.path.exists(INSTALL_TMP): if not os.path.exists(INSTALL_TMP):
@ -862,6 +923,9 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
args_list = [ value[0] for value in args_odict.values() ] args_list = [ value[0] for value in args_odict.values() ]
args_list.append(app_instance_name) args_list.append(app_instance_name)
# Validate domain / path availability for webapps
_validate_and_normalize_webpath(manifest, args_odict, extracted_app_folder)
# Prepare env. var. to pass to script # Prepare env. var. to pass to script
env_dict = _make_environment_dict(args_odict) env_dict = _make_environment_dict(args_odict)
env_dict["YNH_APP_ID"] = app_id env_dict["YNH_APP_ID"] = app_id
@ -917,36 +981,54 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
if os.path.exists(os.path.join(extracted_app_folder, file_to_copy)): if os.path.exists(os.path.join(extracted_app_folder, file_to_copy)):
os.system('cp -R %s/%s %s' % (extracted_app_folder, file_to_copy, app_setting_path)) os.system('cp -R %s/%s %s' % (extracted_app_folder, file_to_copy, app_setting_path))
# Create permission before the install (useful if the install script redefine the permission) # Initialize the main permission for the app
# Note that sync_perm is disabled to avoid triggering a whole bunch of code and messages # After the install, if apps don't have a domain and path defined, the default url '/' is removed from the permission
# can't be sure that we don't have one case when it's needed permission_create(app_instance_name+".main", url="/", allowed=["all_users"])
permission_create(app_instance_name+".main", sync_perm=False)
# Execute the app install script # Execute the app install script
install_retcode = 1 install_failed = True
try: try:
install_retcode = hook_exec( install_retcode = hook_exec(
os.path.join(extracted_app_folder, 'scripts/install'), os.path.join(extracted_app_folder, 'scripts/install'),
args=args_list, env=env_dict args=args_list, env=env_dict
)[0] )[0]
# "Common" app install failure : the script failed and returned exit code != 0
install_failed = True if install_retcode != 0 else False
if install_failed:
error = m18n.n('app_install_script_failed')
logger.exception(m18n.n("app_install_failed", app=app_id, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
# Script got manually interrupted ... N.B. : KeyboardInterrupt does not inherit from Exception
except (KeyboardInterrupt, EOFError): except (KeyboardInterrupt, EOFError):
install_retcode = -1 error = m18n.n('operation_interrupted')
except Exception: logger.exception(m18n.n("app_install_failed", app=app_id, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
# Something wrong happened in Yunohost's code (most probably hook_exec)
except Exception as e:
import traceback import traceback
logger.exception(m18n.n('unexpected_error', error=u"\n" + traceback.format_exc())) error = m18n.n('unexpected_error', error=u"\n" + traceback.format_exc())
logger.exception(m18n.n("app_install_failed", app=app_id, error=error))
failure_message_with_debug_instructions = operation_logger.error(error)
finally: finally:
# Whatever happened (install success or failure) we check if it broke the system
# and warn the user about it
try: try:
broke_the_system = False broke_the_system = False
_assert_system_is_sane_for_app(manifest, "post") _assert_system_is_sane_for_app(manifest, "post")
except Exception as e: except Exception as e:
broke_the_system = True broke_the_system = True
error_msg = operation_logger.error(str(e)) logger.exception(m18n.n("app_install_failed", app=app_id, error=str(e)))
failure_message_with_debug_instructions = operation_logger.error(str(e))
if install_retcode != 0: # If the install failed or broke the system, we remove it
error_msg = operation_logger.error(m18n.n('unexpected_error', error='shell command return code: %s' % install_retcode)) if install_failed or broke_the_system:
# This option is meant for packagers to debug their apps more easily
if no_remove_on_failure:
raise YunohostError("The installation of %s failed, but was not cleaned up as requested by --no-remove-on-failure." % app_id, raw_msg=True)
else:
logger.warning(m18n.n("app_remove_after_failed_install"))
if install_retcode != 0 or broke_the_system:
if not no_remove_on_failure:
# Setup environment for remove script # Setup environment for remove script
env_dict_remove = {} env_dict_remove = {}
env_dict_remove["YNH_APP_ID"] = app_id env_dict_remove["YNH_APP_ID"] = app_id
@ -959,14 +1041,25 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
env=env_dict_remove) env=env_dict_remove)
operation_logger_remove.start() operation_logger_remove.start()
# Try to remove the app
try:
remove_retcode = hook_exec( remove_retcode = hook_exec(
os.path.join(extracted_app_folder, 'scripts/remove'), os.path.join(extracted_app_folder, 'scripts/remove'),
args=[app_instance_name], env=env_dict_remove args=[app_instance_name], env=env_dict_remove
)[0] )[0]
# Here again, calling hook_exec could fail miserably, or get
# manually interrupted (by mistake or because script was stuck)
# In that case we still want to proceed with the rest of the
# removal (permissions, /etc/yunohost/apps/{app} ...)
except (KeyboardInterrupt, EOFError, Exception):
remove_retcode = -1
import traceback
logger.exception(m18n.n('unexpected_error', error=u"\n" + traceback.format_exc()))
# Remove all permission in LDAP # Remove all permission in LDAP
for permission_name in user_permission_list()["permissions"].keys(): for permission_name in user_permission_list()["permissions"].keys():
if permission_name.startswith(app_instance_name+"."): if permission_name.startswith(app_instance_name+"."):
permission_delete(permission_name, force=True) permission_delete(permission_name, force=True, sync_perm=False)
if remove_retcode != 0: if remove_retcode != 0:
msg = m18n.n('app_not_properly_removed', msg = m18n.n('app_not_properly_removed',
@ -985,13 +1078,9 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
shutil.rmtree(app_setting_path) shutil.rmtree(app_setting_path)
shutil.rmtree(extracted_app_folder) shutil.rmtree(extracted_app_folder)
app_ssowatconf() permission_sync_to_user()
if install_retcode == -1: raise YunohostError(failure_message_with_debug_instructions, raw_msg=True)
msg = m18n.n('operation_interrupted') + " " + error_msg
raise YunohostError(msg, raw_msg=True)
msg = error_msg
raise YunohostError(msg, raw_msg=True)
# Clean hooks and add new ones # Clean hooks and add new ones
hook_remove(app_instance_name) hook_remove(app_instance_name)
@ -1009,12 +1098,15 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
os.system('chown -R root: %s' % app_setting_path) os.system('chown -R root: %s' % app_setting_path)
os.system('chown -R admin: %s/scripts' % app_setting_path) os.system('chown -R admin: %s/scripts' % app_setting_path)
# Add path in permission if it's defined in the app install script # If an app doesn't have at least a domain and a path, assume it's not a webapp and remove the default "/" permission
app_settings = _get_app_settings(app_instance_name) app_settings = _get_app_settings(app_instance_name)
domain = app_settings.get('domain', None) domain = app_settings.get('domain', None)
path = app_settings.get('path', None) path = app_settings.get('path', None)
if domain and path: if not (domain and path):
permission_urls(app_instance_name+".main", add=[domain+path], sync_perm=False) permission_url(app_instance_name + ".main", url=None, sync_perm=False)
_migrate_legacy_permissions(app_instance_name)
permission_sync_to_user() permission_sync_to_user()
logger.success(m18n.n('installation_complete')) logger.success(m18n.n('installation_complete'))
@ -1022,6 +1114,34 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
hook_callback('post_app_install', args=args_list, env=env_dict) hook_callback('post_app_install', args=args_list, env=env_dict)
def _migrate_legacy_permissions(app):
from yunohost.permission import user_permission_list, user_permission_update
# Check if app is apparently using the legacy permission management, defined by the presence of something like
# ynh_app_setting_set on unprotected_uris (or yunohost app setting)
install_script_path = os.path.join(APPS_SETTING_PATH, app, 'scripts/install')
install_script_content = open(install_script_path, "r").read()
if not re.search(r"(yunohost app setting|ynh_app_setting_set) .*(unprotected|skipped)_uris", install_script_content):
return
app_settings = _get_app_settings(app)
app_perm_currently_allowed = user_permission_list()["permissions"][app + ".main"]["allowed"]
settings_say_it_should_be_public = (app_settings.get("unprotected_uris", None) == "/"
or app_settings.get("skipped_uris", None) == "/")
# If the current permission says app is protected, but there are legacy rules saying it should be public...
if app_perm_currently_allowed == ["all_users"] and settings_say_it_should_be_public:
# Make it public
user_permission_update(app + ".main", remove="all_users", add="visitors", sync_perm=False)
# If the current permission says app is public, but there are no setting saying it should be public...
if app_perm_currently_allowed == ["visitors"] and not settings_say_it_should_be_public:
# Make is private
user_permission_update(app + ".main", remove="visitors", add="all_users", sync_perm=False)
@is_unit_operation() @is_unit_operation()
def app_remove(operation_logger, app): def app_remove(operation_logger, app):
""" """
@ -1068,11 +1188,24 @@ def app_remove(operation_logger, app):
operation_logger.extra.update({'env': env_dict}) operation_logger.extra.update({'env': env_dict})
operation_logger.flush() operation_logger.flush()
if hook_exec('/tmp/yunohost_remove/scripts/remove', args=args_list, try:
env=env_dict)[0] == 0: ret = hook_exec('/tmp/yunohost_remove/scripts/remove',
logger.success(m18n.n('app_removed', app=app)) args=args_list,
env=env_dict)[0]
# Here again, calling hook_exec could fail miserably, or get
# manually interrupted (by mistake or because script was stuck)
# In that case we still want to proceed with the rest of the
# removal (permissions, /etc/yunohost/apps/{app} ...)
except (KeyboardInterrupt, EOFError, Exception):
ret = -1
import traceback
logger.exception(m18n.n('unexpected_error', error=u"\n" + traceback.format_exc()))
if ret == 0:
logger.success(m18n.n('app_removed', app=app))
hook_callback('post_app_remove', args=args_list, env=env_dict) hook_callback('post_app_remove', args=args_list, env=env_dict)
else:
logger.warning(m18n.n('app_not_properly_removed', app=app))
if os.path.exists(app_setting_path): if os.path.exists(app_setting_path):
shutil.rmtree(app_setting_path) shutil.rmtree(app_setting_path)
@ -1099,6 +1232,8 @@ def app_addaccess(apps, users=[]):
""" """
from yunohost.permission import user_permission_update from yunohost.permission import user_permission_update
logger.warning("/!\\ Packagers ! This app is using the legacy permission system. Please use the new helpers ynh_permission_{create,url,update,delete} and the 'visitors' group to manage permissions.")
output = {} output = {}
for app in apps: for app in apps:
permission = user_permission_update(app+".main", add=users, remove="all_users") permission = user_permission_update(app+".main", add=users, remove="all_users")
@ -1118,6 +1253,8 @@ def app_removeaccess(apps, users=[]):
""" """
from yunohost.permission import user_permission_update from yunohost.permission import user_permission_update
logger.warning("/!\\ Packagers ! This app is using the legacy permission system. Please use the new helpers ynh_permission_{create,url,update,delete} and the 'visitors' group to manage permissions.")
output = {} output = {}
for app in apps: for app in apps:
permission = user_permission_update(app+".main", remove=users) permission = user_permission_update(app+".main", remove=users)
@ -1136,6 +1273,8 @@ def app_clearaccess(apps):
""" """
from yunohost.permission import user_permission_reset from yunohost.permission import user_permission_reset
logger.warning("/!\\ Packagers ! This app is using the legacy permission system. Please use the new helpers ynh_permission_{create,url,update,delete} and the 'visitors' group to manage permissions.")
output = {} output = {}
for app in apps: for app in apps:
permission = user_permission_reset(app+".main") permission = user_permission_reset(app+".main")
@ -1144,28 +1283,6 @@ def app_clearaccess(apps):
return {'allowed_users': output} return {'allowed_users': output}
def app_debug(app):
"""
Display debug informations for an app
Keyword argument:
app
"""
manifest = _get_manifest_of_app(os.path.join(APPS_SETTING_PATH, app))
return {
'name': manifest['id'],
'label': manifest['name'],
'services': [{
"name": x,
"logs": [{
"file_name": y,
"file_content": "\n".join(z),
} for (y, z) in sorted(service_log(x).items(), key=lambda x: x[0])],
} for x in sorted(manifest.get("services", []))]
}
@is_unit_operation() @is_unit_operation()
def app_makedefault(operation_logger, app, domain=None): def app_makedefault(operation_logger, app, domain=None):
""" """
@ -1193,25 +1310,21 @@ def app_makedefault(operation_logger, app, domain=None):
raise YunohostError('app_make_default_location_already_used', app=app, domain=app_domain, raise YunohostError('app_make_default_location_already_used', app=app, domain=app_domain,
other_app=app_map(raw=True)[domain]["/"]["id"]) other_app=app_map(raw=True)[domain]["/"]["id"])
try: # TODO / FIXME : current trick is to add this to conf.json.persisten
with open('/etc/ssowat/conf.json.persistent') as json_conf: # This is really not robust and should be improved
ssowat_conf = json.loads(str(json_conf.read())) # e.g. have a flag in /etc/yunohost/apps/$app/ to say that this is the
except ValueError as e: # default app or idk...
raise YunohostError('ssowat_persistent_conf_read_error', error=e) if not os.path.exists('/etc/ssowat/conf.json.persistent'):
except IOError:
ssowat_conf = {} ssowat_conf = {}
else:
ssowat_conf = read_json('/etc/ssowat/conf.json.persistent')
if 'redirected_urls' not in ssowat_conf: if 'redirected_urls' not in ssowat_conf:
ssowat_conf['redirected_urls'] = {} ssowat_conf['redirected_urls'] = {}
ssowat_conf['redirected_urls'][domain + '/'] = app_domain + app_path ssowat_conf['redirected_urls'][domain + '/'] = app_domain + app_path
try: write_to_json('/etc/ssowat/conf.json.persistent', ssowat_conf)
with open('/etc/ssowat/conf.json.persistent', 'w+') as f:
json.dump(ssowat_conf, f, sort_keys=True, indent=4)
except IOError as e:
raise YunohostError('ssowat_persistent_conf_write_error', error=e)
os.system('chmod 644 /etc/ssowat/conf.json.persistent') os.system('chmod 644 /etc/ssowat/conf.json.persistent')
logger.success(m18n.n('ssowat_conf_updated')) logger.success(m18n.n('ssowat_conf_updated'))
@ -1236,16 +1349,25 @@ def app_setting(app, key, value=None, delete=False):
except Exception as e: except Exception as e:
logger.debug("cannot get app setting '%s' for '%s' (%s)", key, app, e) logger.debug("cannot get app setting '%s' for '%s' (%s)", key, app, e)
return None return None
else:
if delete and key in app_settings: if delete and key in app_settings:
del app_settings[key] del app_settings[key]
else: else:
# FIXME: Allow multiple values for some keys? # FIXME: Allow multiple values for some keys?
if key in ['redirected_urls', 'redirected_regex']: if key in ['redirected_urls', 'redirected_regex']:
value = yaml.load(value) value = yaml.load(value)
if any(key.startswith(word+"_") for word in ["unprotected", "protected", "skipped"]):
logger.warning("/!\\ Packagers! This app is still using the skipped/protected/unprotected_uris/regex settings which are now obsolete and deprecated... Instead, you should use the new helpers 'ynh_permission_{create,urls,update,delete}' and the 'visitors' group to initialize the public/private access. Check out the documentation at the bottom of yunohost.org/groups_and_permissions to learn how to use the new permission mechanism.")
app_settings[key] = value app_settings[key] = value
_set_app_settings(app, app_settings) _set_app_settings(app, app_settings)
# Fucking legacy permission management.
# We need this because app temporarily set the app as unprotected to configure it with curl...
if key.startswith("unprotected_") or key.startswith("skipped_") and value == "/":
from permission import user_permission_update
user_permission_update(app + ".main", remove="all_users", add="visitors")
def app_checkport(port): def app_checkport(port):
""" """
@ -1407,6 +1529,7 @@ def app_ssowatconf():
main_domain = _get_maindomain() main_domain = _get_maindomain()
domains = domain_list()['domains'] domains = domain_list()['domains']
all_permissions = user_permission_list(full=True)['permissions']
skipped_urls = [] skipped_urls = []
skipped_regex = [] skipped_regex = []
@ -1428,34 +1551,70 @@ def app_ssowatconf():
return s.split(',') if s else [] return s.split(',') if s else []
for app in apps_list: for app in apps_list:
with open(APPS_SETTING_PATH + app['id'] + '/settings.yml') as f:
app_settings = yaml.load(f)
app_settings = read_yaml(APPS_SETTING_PATH + app['id'] + '/settings.yml')
if 'domain' not in app_settings:
continue
if 'path' not in app_settings:
continue
# This 'no_sso' settings sound redundant to not having $path defined ....
# At least from what I can see, all apps using it don't have a path defined ...
if 'no_sso' in app_settings: if 'no_sso' in app_settings:
continue continue
for item in _get_setting(app_settings, 'skipped_uris'): domain = app_settings['domain']
if item[-1:] == '/': path = app_settings['path'].rstrip('/')
item = item[:-1]
skipped_urls.append(app_settings['domain'] + app_settings['path'].rstrip('/') + item) def _sanitized_absolute_url(perm_url):
for item in _get_setting(app_settings, 'skipped_regex'): # Nominal case : url is relative to the app's path
skipped_regex.append(item) if perm_url.startswith("/"):
for item in _get_setting(app_settings, 'unprotected_uris'): perm_domain = domain
if item[-1:] == '/': perm_path = path + perm_url.rstrip("/")
item = item[:-1] # Otherwise, the urls starts with a domain name, like domain.tld/foo/bar
unprotected_urls.append(app_settings['domain'] + app_settings['path'].rstrip('/') + item) # We want perm_domain = domain.tld and perm_path = "/foo/bar"
for item in _get_setting(app_settings, 'unprotected_regex'): else:
unprotected_regex.append(item) perm_domain, perm_path = perm_url.split("/", 1)
for item in _get_setting(app_settings, 'protected_uris'): perm_path = "/" + perm_path.rstrip("/")
if item[-1:] == '/':
item = item[:-1] return perm_domain + perm_path
protected_urls.append(app_settings['domain'] + app_settings['path'].rstrip('/') + item)
for item in _get_setting(app_settings, 'protected_regex'): # Skipped
protected_regex.append(item) skipped_urls += [_sanitized_absolute_url(uri) for uri in _get_setting(app_settings, 'skipped_uris')]
if 'redirected_urls' in app_settings: skipped_regex += _get_setting(app_settings, 'skipped_regex')
redirected_urls.update(app_settings['redirected_urls'])
if 'redirected_regex' in app_settings: # Redirected
redirected_regex.update(app_settings['redirected_regex']) redirected_urls.update(app_settings.get('redirected_urls', {}))
redirected_regex.update(app_settings.get('redirected_regex', {}))
# Legacy permission system using (un)protected_uris and _regex managed in app settings...
unprotected_urls += [_sanitized_absolute_url(uri) for uri in _get_setting(app_settings, 'unprotected_uris')]
protected_urls += [_sanitized_absolute_url(uri) for uri in _get_setting(app_settings, 'protected_uris')]
unprotected_regex += _get_setting(app_settings, 'unprotected_regex')
protected_regex += _get_setting(app_settings, 'protected_regex')
# New permission system
this_app_perms = {name: info for name, info in all_permissions.items() if name.startswith(app['id'] + ".")}
for perm_name, perm_info in this_app_perms.items():
# Ignore permissions for which there's no url defined
if not perm_info["url"]:
continue
# FIXME : gotta handle regex-urls here... meh
url = _sanitized_absolute_url(perm_info["url"])
if "visitors" in perm_info["allowed"]:
unprotected_urls.append(url)
# Legacy stuff : we remove now unprotected-urls that might have been declared as protected earlier...
protected_urls = [u for u in protected_urls if u != url]
else:
# TODO : small optimization to implement : we don't need to explictly add all the app roots
protected_urls.append(url)
# Legacy stuff : we remove now unprotected-urls that might have been declared as protected earlier...
unprotected_urls = [u for u in unprotected_urls if u != url]
for domain in domains: for domain in domains:
skipped_urls.extend([domain + '/yunohost/admin', domain + '/yunohost/api']) skipped_urls.extend([domain + '/yunohost/admin', domain + '/yunohost/api'])
@ -1464,10 +1623,14 @@ def app_ssowatconf():
skipped_regex.append("^[^/]*/%.well%-known/acme%-challenge/.*$") skipped_regex.append("^[^/]*/%.well%-known/acme%-challenge/.*$")
skipped_regex.append("^[^/]*/%.well%-known/autoconfig/mail/config%-v1%.1%.xml.*$") skipped_regex.append("^[^/]*/%.well%-known/autoconfig/mail/config%-v1%.1%.xml.*$")
permissions_per_url = {} permissions_per_url = {}
for permission_name, permission_infos in user_permission_list(full=True)['permissions'].items(): for perm_name, perm_info in all_permissions.items():
for url in permission_infos["urls"]: # Ignore permissions for which there's no url defined
permissions_per_url[url] = permission_infos['corresponding_users'] if not perm_info["url"]:
continue
permissions_per_url[perm_info["url"]] = perm_info['corresponding_users']
conf_dict = { conf_dict = {
'portal_domain': main_domain, 'portal_domain': main_domain,
@ -2554,8 +2717,7 @@ def _parse_args_for_action(action, args={}):
def _parse_args_in_yunohost_format(args, action_args): def _parse_args_in_yunohost_format(args, action_args):
"""Parse arguments store in either manifest.json or actions.json """Parse arguments store in either manifest.json or actions.json
""" """
from yunohost.domain import (domain_list, _get_maindomain, from yunohost.domain import domain_list, _get_maindomain
_get_conflicting_apps, _normalize_domain_path)
from yunohost.user import user_info, user_list from yunohost.user import user_info, user_list
args_dict = OrderedDict() args_dict = OrderedDict()
@ -2648,10 +2810,8 @@ def _parse_args_in_yunohost_format(args, action_args):
if arg_value not in domain_list()['domains']: if arg_value not in domain_list()['domains']:
raise YunohostError('app_argument_invalid', name=arg_name, error=m18n.n('domain_unknown')) raise YunohostError('app_argument_invalid', name=arg_name, error=m18n.n('domain_unknown'))
elif arg_type == 'user': elif arg_type == 'user':
try: if not arg_value in user_list()["users"].keys():
user_info(arg_value) raise YunohostError('app_argument_invalid', name=arg_name, error=m18n.n('user_unknown', user=arg_value))
except YunohostError as e:
raise YunohostError('app_argument_invalid', name=arg_name, error=e)
elif arg_type == 'app': elif arg_type == 'app':
if not _is_installed(arg_value): if not _is_installed(arg_value):
raise YunohostError('app_argument_invalid', name=arg_name, error=m18n.n('app_unknown')) raise YunohostError('app_argument_invalid', name=arg_name, error=m18n.n('app_unknown'))
@ -2673,7 +2833,12 @@ def _parse_args_in_yunohost_format(args, action_args):
assert_password_is_strong_enough('user', arg_value) assert_password_is_strong_enough('user', arg_value)
args_dict[arg_name] = (arg_value, arg_type) args_dict[arg_name] = (arg_value, arg_type)
# END loop over action_args... return args_dict
def _validate_and_normalize_webpath(manifest, args_dict, app_folder):
from yunohost.domain import _get_conflicting_apps, _normalize_domain_path
# If there's only one "domain" and "path", validate that domain/path # If there's only one "domain" and "path", validate that domain/path
# is an available url and normalize the path. # is an available url and normalize the path.
@ -2705,7 +2870,25 @@ def _parse_args_in_yunohost_format(args, action_args):
# standard path format to deal with no matter what the user inputted) # standard path format to deal with no matter what the user inputted)
args_dict[path_args[0][0]] = (path, "path") args_dict[path_args[0][0]] = (path, "path")
return args_dict # This is likely to be a full-domain app...
elif len(domain_args) == 1 and len(path_args) == 0:
# Confirm that this is a full-domain app This should cover most cases
# ... though anyway the proper solution is to implement some mechanism
# in the manifest for app to declare that they require a full domain
# (among other thing) so that we can dynamically check/display this
# requirement on the webadmin form and not miserably fail at submit time
# Full-domain apps typically declare something like path_url="/" or path=/
# and use ynh_webpath_register or yunohost_app_checkurl inside the install script
install_script_content = open(os.path.join(app_folder, 'scripts/install')).read()
if re.search(r"\npath(_url)?=[\"']?/[\"']?\n", install_script_content) \
and re.search(r"(ynh_webpath_register|yunohost app checkurl)", install_script_content):
domain = domain_args[0][1]
if _get_conflicting_apps(domain, "/"):
raise YunohostError('app_full_domain_unavailable', domain=domain)
def _make_environment_dict(args_dict, prefix="APP_ARG_"): def _make_environment_dict(args_dict, prefix="APP_ARG_"):

View file

@ -602,10 +602,10 @@ class BackupManager():
env=env_dict, env=env_dict,
chdir=self.work_dir) chdir=self.work_dir)
ret_succeed = {hook: {path:result["state"] for path, result in infos.items()} ret_succeed = {hook: [path for path, result in infos.items() if result["state"] == "succeed"]
for hook, infos in ret.items() for hook, infos in ret.items()
if any(result["state"] == "succeed" for result in infos.values())} if any(result["state"] == "succeed" for result in infos.values())}
ret_failed = {hook: {path:result["state"] for path, result in infos.items.items()} ret_failed = {hook: [path for path, result in infos.items.items() if result["state"] == "failed"]
for hook, infos in ret.items() for hook, infos in ret.items()
if any(result["state"] == "failed" for result in infos.values())} if any(result["state"] == "failed" for result in infos.values())}
@ -1189,7 +1189,7 @@ class RestoreManager():
return return
from yunohost.user import user_group_list from yunohost.user import user_group_list
from yunohost.permission import permission_create, permission_delete, user_permission_update, user_permission_list from yunohost.permission import permission_create, permission_delete, user_permission_update, user_permission_list, permission_sync_to_user
# Backup old permission for apps # Backup old permission for apps
# We need to do that because in case of an app is installed we can't remove the permission for this app # We need to do that because in case of an app is installed we can't remove the permission for this app
@ -1245,14 +1245,16 @@ class RestoreManager():
# Remove all permission for all app which is still in the LDAP # Remove all permission for all app which is still in the LDAP
for permission_name in user_permission_list(ignore_system_perms=True)["permissions"].keys(): for permission_name in user_permission_list(ignore_system_perms=True)["permissions"].keys():
permission_delete(permission_name, force=True) permission_delete(permission_name, force=True, sync_perm=False)
# Restore permission for the app which is installed # Restore permission for the app which is installed
for permission_name, permission_infos in old_apps_permission.items(): for permission_name, permission_infos in old_apps_permission.items():
app_name = permission_name.split(".")[0] app_name = permission_name.split(".")[0]
if _is_installed(app_name): if _is_installed(app_name):
permission_create(permission_name, urls=permission_infos["urls"], sync_perm=False) permission_create(permission_name, url=permission_infos["url"], allowed=permission_infos["allowed"], sync_perm=False)
user_permission_update(permission_name, remove="all_users", add=permission_infos["allowed"])
permission_sync_to_user()
def _restore_apps(self): def _restore_apps(self):
"""Restore all apps targeted""" """Restore all apps targeted"""
@ -1290,7 +1292,7 @@ class RestoreManager():
restore_app_failed -- Raised if the restore bash script failed restore_app_failed -- Raised if the restore bash script failed
""" """
from yunohost.user import user_group_list from yunohost.user import user_group_list
from yunohost.permission import permission_create, permission_delete, user_permission_list, user_permission_update from yunohost.permission import permission_create, permission_delete, user_permission_list, user_permission_update, permission_sync_to_user
def copytree(src, dst, symlinks=False, ignore=None): def copytree(src, dst, symlinks=False, ignore=None):
for item in os.listdir(src): for item in os.listdir(src):
@ -1362,15 +1364,15 @@ class RestoreManager():
for permission_name, permission_infos in permissions.items(): for permission_name, permission_infos in permissions.items():
permission_create(permission_name, urls=permission_infos.get("urls", []))
if "allowed" not in permission_infos: if "allowed" not in permission_infos:
logger.warning("'allowed' key corresponding to allowed groups for permission %s not found when restoring app %s … You might have to reconfigure permissions yourself." % (permission_name, app_instance_name)) logger.warning("'allowed' key corresponding to allowed groups for permission %s not found when restoring app %s … You might have to reconfigure permissions yourself." % (permission_name, app_instance_name))
should_be_allowed = ["all_users"]
else: else:
should_be_allowed = [g for g in permission_infos["allowed"] if g in existing_groups] should_be_allowed = [g for g in permission_infos["allowed"] if g in existing_groups]
current_allowed = user_permission_list()["permissions"][permission_name]["allowed"]
if should_be_allowed != current_allowed: permission_create(permission_name, url=permission_infos.get("url", None), allowed=should_be_allowed, sync_perm=False)
user_permission_update(permission_name, remove=current_allowed, add=should_be_allowed)
permission_sync_to_user()
os.remove('%s/permissions.yml' % app_settings_new_path) os.remove('%s/permissions.yml' % app_settings_new_path)
else: else:
@ -2371,6 +2373,15 @@ def backup_info(name, with_details=False, human_readable=False):
if "size_details" in info.keys(): if "size_details" in info.keys():
for category in ["apps", "system"]: for category in ["apps", "system"]:
for name, key_info in info[category].items(): for name, key_info in info[category].items():
if category == "system":
# Stupid legacy fix for weird format between 3.5 and 3.6
if isinstance(key_info, dict):
key_info = key_info.keys()
info[category][name] = key_info = {"paths": key_info}
else:
info[category][name] = key_info
if name in info["size_details"][category].keys(): if name in info["size_details"][category].keys():
key_info["size"] = info["size_details"][category][name] key_info["size"] = info["size_details"][category][name]
if human_readable: if human_readable:

View file

@ -9,7 +9,7 @@ from moulinette.utils.filesystem import read_yaml
from yunohost.tools import Migration from yunohost.tools import Migration
from yunohost.user import user_group_create, user_group_update from yunohost.user import user_group_create, user_group_update
from yunohost.app import app_setting, app_list from yunohost.app import app_setting, app_list
from yunohost.regenconf import regen_conf from yunohost.regenconf import regen_conf, BACKUP_CONF_DIR
from yunohost.permission import permission_create, user_permission_update, permission_sync_to_user from yunohost.permission import permission_create, user_permission_update, permission_sync_to_user
logger = getActionLogger('yunohost.migration') logger = getActionLogger('yunohost.migration')
@ -60,16 +60,21 @@ class MyMigration(Migration):
ldap_map = read_yaml('/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml') ldap_map = read_yaml('/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml')
try: try:
self.remove_if_exists("cn=sftpusers,ou=groups")
self.remove_if_exists("ou=permission") self.remove_if_exists("ou=permission")
self.remove_if_exists('cn=all_users,ou=groups') self.remove_if_exists('ou=groups')
attr_dict = ldap_map['parents']['ou=permission'] attr_dict = ldap_map['parents']['ou=permission']
ldap.add('ou=permission', attr_dict) ldap.add('ou=permission', attr_dict)
attr_dict = ldap_map['parents']['ou=groups']
ldap.add('ou=groups', attr_dict)
attr_dict = ldap_map['children']['cn=all_users,ou=groups'] attr_dict = ldap_map['children']['cn=all_users,ou=groups']
ldap.add('cn=all_users,ou=groups', attr_dict) ldap.add('cn=all_users,ou=groups', attr_dict)
attr_dict = ldap_map['children']['cn=visitors,ou=groups']
ldap.add('cn=visitors,ou=groups', attr_dict)
for rdn, attr_dict in ldap_map['depends_children'].items(): for rdn, attr_dict in ldap_map['depends_children'].items():
ldap.add(rdn, attr_dict) ldap.add(rdn, attr_dict)
except Exception as e: except Exception as e:
@ -102,13 +107,21 @@ class MyMigration(Migration):
path = app_setting(app, 'path') path = app_setting(app, 'path')
domain = app_setting(app, 'domain') domain = app_setting(app, 'domain')
urls = [domain + path] if domain and path else None url = "/" if domain and path else None
permission_create(app+".main", urls=urls, sync_perm=False)
if permission: if permission:
allowed_group = permission.split(',') allowed_groups = permission.split(',')
user_permission_update(app+".main", remove="all_users", add=allowed_group, sync_perm=False) else:
allowed_groups = ["all_users"]
permission_create(app+".main", url=url, allowed=allowed_groups, sync_perm=False)
app_setting(app, 'allowed_users', delete=True) app_setting(app, 'allowed_users', delete=True)
# Migrate classic public app still using the legacy unprotected_uris
if app_setting(app, "unprotected_uris") == "/" or app_setting(app, "skipped_uris") == "/":
user_permission_update(app+".main", remove="all_users", add="visitors", sync_perm=False)
permission_sync_to_user()
def run(self): def run(self):
# FIXME : what do we really want to do here ... # FIXME : what do we really want to do here ...
@ -119,7 +132,7 @@ class MyMigration(Migration):
ldap_regen_conf_status = regen_conf(names=['slapd'], dry_run=True) ldap_regen_conf_status = regen_conf(names=['slapd'], dry_run=True)
# By this we check if the have been customized # By this we check if the have been customized
if ldap_regen_conf_status and ldap_regen_conf_status['slapd']['pending']: if ldap_regen_conf_status and ldap_regen_conf_status['slapd']['pending']:
raise YunohostError("migration_0011_LDAP_config_dirty") logger.warning(m18n.n("migration_0011_slapd_config_will_be_overwritten", conf_backup_folder=BACKUP_CONF_DIR))
# Backup LDAP and the apps settings before to do the migration # Backup LDAP and the apps settings before to do the migration
logger.info(m18n.n("migration_0011_backup_before_migration")) logger.info(m18n.n("migration_0011_backup_before_migration"))

View file

@ -196,7 +196,7 @@ def hook_list(action, list_by='name', show_info=False):
else: else:
_append_folder(result, HOOK_FOLDER) _append_folder(result, HOOK_FOLDER)
except OSError: except OSError:
logger.debug("system hook folder not found for action '%s' in %s", logger.debug("No default hook for action '%s' in %s",
action, HOOK_FOLDER) action, HOOK_FOLDER)
try: try:
@ -207,7 +207,7 @@ def hook_list(action, list_by='name', show_info=False):
else: else:
_append_folder(result, CUSTOM_HOOK_FOLDER) _append_folder(result, CUSTOM_HOOK_FOLDER)
except OSError: except OSError:
logger.debug("custom hook folder not found for action '%s' in %s", logger.debug("No custom hook for action '%s' in %s",
action, CUSTOM_HOOK_FOLDER) action, CUSTOM_HOOK_FOLDER)
return {'hooks': result} return {'hooks': result}

View file

@ -315,7 +315,8 @@ class RedactingFormatter(Formatter):
try: try:
# This matches stuff like db_pwd=the_secret or admin_password=other_secret # This matches stuff like db_pwd=the_secret or admin_password=other_secret
# (the secret part being at least 3 chars to avoid catching some lines like just "db_pwd=") # (the secret part being at least 3 chars to avoid catching some lines like just "db_pwd=")
match = re.search(r'(pwd|pass|password|secret|key|token)=(\S{3,})$', record.strip()) # For 'key', we require to at least have one word char [a-zA-Z0-9_] before it to avoid catching "--key" used in many helpers
match = re.search(r'(pwd|pass|password|secret|\wkey|token)=(\S{3,})$', record.strip())
if match and match.group(2) not in self.data_to_redact: if match and match.group(2) not in self.data_to_redact:
self.data_to_redact.append(match.group(2)) self.data_to_redact.append(match.group(2))
except Exception as e: except Exception as e:
@ -502,6 +503,9 @@ class OperationLogger(object):
The missing of the message below could help to see an electrical The missing of the message below could help to see an electrical
shortage. shortage.
""" """
if self.ended_at is not None or self.started_at is None:
return
else:
self.error(m18n.n('log_operation_unit_unclosed_properly')) self.error(m18n.n('log_operation_unit_unclosed_properly'))

View file

@ -73,7 +73,7 @@ def user_permission_list(short=False, full=False, ignore_system_perms=False):
if full: if full:
permissions[name]["corresponding_users"] = [_ldap_path_extract(p, "uid") for p in infos.get('inheritPermission', [])] permissions[name]["corresponding_users"] = [_ldap_path_extract(p, "uid") for p in infos.get('inheritPermission', [])]
permissions[name]["urls"] = infos.get("URL", []) permissions[name]["url"] = infos.get("URL", [None])[0]
if short: if short:
permissions = permissions.keys() permissions = permissions.keys()
@ -100,6 +100,10 @@ def user_permission_update(operation_logger, permission, add=None, remove=None,
if "." not in permission: if "." not in permission:
permission = permission + ".main" permission = permission + ".main"
# Refuse to add "visitors" to mail, xmpp ... they require an account to make sense.
if add and "visitors" in add and permission.split(".")[0] in SYSTEM_PERMS:
raise YunohostError('permission_require_account', permission=permission)
# Fetch currently allowed groups for this permission # Fetch currently allowed groups for this permission
existing_permission = user_permission_list(full=True)["permissions"].get(permission, None) existing_permission = user_permission_list(full=True)["permissions"].get(permission, None)
@ -142,16 +146,16 @@ def user_permission_update(operation_logger, permission, add=None, remove=None,
# we shall warn the users that they should probably choose between one or the other, # we shall warn the users that they should probably choose between one or the other,
# because the current situation is probably not what they expect / is temporary ? # because the current situation is probably not what they expect / is temporary ?
if len(new_allowed_groups) > 1 and "all_users" in new_allowed_groups: if len(new_allowed_groups) > 1:
# FIXME : i18n if "all_users" in new_allowed_groups:
# FIXME : write a better explanation ? logger.warning(m18n.n("permission_currently_allowed_for_all_users"))
logger.warning("This permission is currently enabled for all users in addition to other groups. You probably want to either remove the 'all_users' permission or remove the specific groups currently allowed.") if "visitors" in new_allowed_groups:
logger.warning(m18n.n("permission_currently_allowed_for_visitors"))
# Don't update LDAP if we update exactly the same values # Don't update LDAP if we update exactly the same values
if set(new_allowed_groups) == set(current_allowed_groups): if set(new_allowed_groups) == set(current_allowed_groups):
# FIXME : i18n logger.warning(m18n.n("permission_already_up_to_date"))
logger.warning("The permission was not updated all addition/removal requests already match the current state.") return existing_permission
return
# Commit the new allowed group list # Commit the new allowed group list
@ -212,6 +216,10 @@ def user_permission_reset(operation_logger, permission, sync_perm=True):
if existing_permission is None: if existing_permission is None:
raise YunohostError('permission_not_found', permission=permission) raise YunohostError('permission_not_found', permission=permission)
if existing_permission["allowed"] == ["all_users"]:
logger.warning(m18n.n("permission_already_up_to_date"))
return
# Update permission with default (all_users) # Update permission with default (all_users)
operation_logger.related_to.append(('app', permission.split(".")[0])) operation_logger.related_to.append(('app', permission.split(".")[0]))
@ -251,21 +259,34 @@ def user_permission_reset(operation_logger, permission, sync_perm=True):
# #
# The followings methods are *not* directly exposed. # The followings methods are *not* directly exposed.
# They are used to create/delete the permissions (e.g. during app install/remove) # They are used to create/delete the permissions (e.g. during app install/remove)
# and by some app helpers to possibly add additional permissions and tweak the urls # and by some app helpers to possibly add additional permissions
# #
# #
@is_unit_operation() @is_unit_operation()
def permission_create(operation_logger, permission, urls=None, sync_perm=True): def permission_create(operation_logger, permission, url=None, allowed=None, sync_perm=True):
""" """
Create a new permission for a specific application Create a new permission for a specific application
Keyword argument: Keyword argument:
permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors) permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors)
urls -- list of urls to specify for the permission url -- (optional) URL for which access will be allowed/forbidden
allowed -- (optional) A list of group/user to allow for the permission
If provided, 'url' is assumed to be relative to the app domain/path if they
start with '/'. For example:
/ -> domain.tld/app
/admin -> domain.tld/app/admin
domain.tld/app/api -> domain.tld/app/api
'url' can be later treated as a regex if it starts with "re:".
For example:
re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
""" """
from yunohost.user import user_group_list
from yunohost.utils.ldap import _get_ldap_interface from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface() ldap = _get_ldap_interface()
@ -292,12 +313,22 @@ def permission_create(operation_logger, permission, urls=None, sync_perm=True):
'gidNumber': gid, 'gidNumber': gid,
} }
# If who should be allowed is explicitly provided, use this info
if allowed:
if not isinstance(allowed, list):
allowed = [allowed]
# (though first we validate that the targets actually exist)
all_existing_groups = user_group_list()['groups'].keys()
for g in allowed:
if g not in all_existing_groups:
raise YunohostError('group_unknown', group=g)
attr_dict['groupPermission'] = ['cn=%s,ou=groups,dc=yunohost,dc=org' % g for g in allowed]
# For main permission, we add all users by default # For main permission, we add all users by default
if permission.endswith(".main"): elif permission.endswith(".main"):
attr_dict['groupPermission'] = ['cn=all_users,ou=groups,dc=yunohost,dc=org'] attr_dict['groupPermission'] = ['cn=all_users,ou=groups,dc=yunohost,dc=org']
if urls: if url:
attr_dict['URL'] = [_normalize_url(url) for url in urls] attr_dict['URL'] = url
operation_logger.related_to.append(('app', permission.split(".")[0])) operation_logger.related_to.append(('app', permission.split(".")[0]))
operation_logger.start() operation_logger.start()
@ -315,15 +346,13 @@ def permission_create(operation_logger, permission, urls=None, sync_perm=True):
@is_unit_operation() @is_unit_operation()
def permission_urls(operation_logger, permission, add=None, remove=None, sync_perm=True): def permission_url(operation_logger, permission, url=None, sync_perm=True):
""" """
Update urls related to a permission for a specific application Update urls related to a permission for a specific application
Keyword argument: Keyword argument:
permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors) permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors)
add -- List of urls to add url -- (optional) URL for which access will be allowed/forbidden
remove -- List of urls to remove
""" """
from yunohost.utils.ldap import _get_ldap_interface from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface() ldap = _get_ldap_interface()
@ -335,19 +364,9 @@ def permission_urls(operation_logger, permission, add=None, remove=None, sync_pe
raise YunohostError('permission_not_found', permission=permission) raise YunohostError('permission_not_found', permission=permission)
# Compute new url list # Compute new url list
old_url = existing_permission["url"]
new_urls = copy.copy(existing_permission["urls"]) if old_url == url:
if add:
urls_to_add = [add] if not isinstance(add, list) else add
urls_to_add = [_normalize_url(url) for url in urls_to_add]
new_urls += urls_to_add
if remove:
urls_to_remove = [remove] if not isinstance(remove, list) else remove
urls_to_remove = [_normalize_url(url) for url in urls_to_remove]
new_urls = [u for u in new_urls if u not in urls_to_remove]
if set(new_urls) == set(existing_permission["urls"]):
logger.warning(m18n.n('permission_update_nothing_to_do')) logger.warning(m18n.n('permission_update_nothing_to_do'))
return existing_permission return existing_permission
@ -357,7 +376,7 @@ def permission_urls(operation_logger, permission, add=None, remove=None, sync_pe
operation_logger.start() operation_logger.start()
try: try:
ldap.update('cn=%s,ou=permission' % permission, {'URL': new_urls}) ldap.update('cn=%s,ou=permission' % permission, {'URL': [url]})
except Exception as e: except Exception as e:
raise YunohostError('permission_update_failed', permission=permission, error=e) raise YunohostError('permission_update_failed', permission=permission, error=e)
@ -452,11 +471,3 @@ def permission_sync_to_user():
# Reload unscd, otherwise the group ain't propagated to the LDAP database # Reload unscd, otherwise the group ain't propagated to the LDAP database
os.system('nscd --invalidate=passwd') os.system('nscd --invalidate=passwd')
os.system('nscd --invalidate=group') os.system('nscd --invalidate=group')
def _normalize_url(url):
from yunohost.domain import _normalize_domain_path
domain = url[:url.index('/')]
path = url[url.index('/'):]
domain, path = _normalize_domain_path(domain, path)
return domain + path

View file

@ -1,9 +1,32 @@
import pytest
import sys import sys
import moulinette import moulinette
from moulinette import m18n
from yunohost.utils.error import YunohostError
from contextlib import contextmanager
sys.path.append("..") sys.path.append("..")
@contextmanager
def message(mocker, key, **kwargs):
mocker.spy(m18n, "n")
yield
m18n.n.assert_any_call(key, **kwargs)
@contextmanager
def raiseYunohostError(mocker, key, **kwargs):
with pytest.raises(YunohostError) as e_info:
yield
assert e_info._excinfo[1].key == key
if kwargs:
assert e_info._excinfo[1].kwargs == kwargs
def pytest_addoption(parser): def pytest_addoption(parser):
parser.addoption("--yunodebug", action="store_true", default=False) parser.addoption("--yunodebug", action="store_true", default=False)

View file

@ -4,6 +4,8 @@ import pytest
import shutil import shutil
import requests import requests
from conftest import message, raiseYunohostError
from moulinette import m18n from moulinette import m18n
from moulinette.utils.filesystem import mkdir from moulinette.utils.filesystem import mkdir
@ -36,16 +38,22 @@ def clean():
if _is_installed("legacy_app"): if _is_installed("legacy_app"):
app_remove("legacy_app") app_remove("legacy_app")
if _is_installed("full_domain_app"):
app_remove("full_domain_app")
to_remove = [] to_remove = []
to_remove += glob.glob("/etc/nginx/conf.d/*.d/*legacy*") to_remove += glob.glob("/etc/nginx/conf.d/*.d/*legacy*")
to_remove += glob.glob("/etc/nginx/conf.d/*.d/*full_domain*")
to_remove += glob.glob("/etc/nginx/conf.d/*.d/*break_yo_system*") to_remove += glob.glob("/etc/nginx/conf.d/*.d/*break_yo_system*")
for filepath in to_remove: for filepath in to_remove:
os.remove(filepath) os.remove(filepath)
to_remove = [] to_remove = []
to_remove += glob.glob("/etc/yunohost/apps/*legacy_app*") to_remove += glob.glob("/etc/yunohost/apps/*legacy_app*")
to_remove += glob.glob("/etc/yunohost/apps/*full_domain_app*")
to_remove += glob.glob("/etc/yunohost/apps/*break_yo_system*") to_remove += glob.glob("/etc/yunohost/apps/*break_yo_system*")
to_remove += glob.glob("/var/www/*legacy*") to_remove += glob.glob("/var/www/*legacy*")
to_remove += glob.glob("/var/www/*full_domain*")
for folderpath in to_remove: for folderpath in to_remove:
shutil.rmtree(folderpath, ignore_errors=True) shutil.rmtree(folderpath, ignore_errors=True)
@ -107,16 +115,23 @@ def app_is_not_installed(domain, app):
def app_is_exposed_on_http(domain, path, message_in_page): def app_is_exposed_on_http(domain, path, message_in_page):
try: try:
r = requests.get("http://127.0.0.1" + path + "/", headers={"Host": domain}, timeout=10) r = requests.get("http://127.0.0.1" + path + "/", headers={"Host": domain}, timeout=10, verify=False)
return r.status_code == 200 and message_in_page in r.text return r.status_code == 200 and message_in_page in r.text
except Exception: except Exception as e:
return False return False
def install_legacy_app(domain, path): def install_legacy_app(domain, path, public=True):
app_install("./tests/apps/legacy_app_ynh", app_install("./tests/apps/legacy_app_ynh",
args="domain=%s&path=%s" % (domain, path), args="domain=%s&path=%s&is_public=%s" % (domain, path, 1 if public else 0),
force=True)
def install_full_domain_app(domain):
app_install("./tests/apps/full_domain_app_ynh",
args="domain=%s" % domain,
force=True) force=True)
@ -167,13 +182,7 @@ def test_legacy_app_install_secondary_domain_on_root(secondary_domain):
def test_legacy_app_install_private(secondary_domain): def test_legacy_app_install_private(secondary_domain):
install_legacy_app(secondary_domain, "/legacy") install_legacy_app(secondary_domain, "/legacy", public=False)
settings = open("/etc/yunohost/apps/legacy_app/settings.yml", "r").read()
new_settings = settings.replace("\nunprotected_uris: /", "")
assert new_settings != settings
open("/etc/yunohost/apps/legacy_app/settings.yml", "w").write(new_settings)
app_ssowatconf()
assert app_is_installed(secondary_domain, "legacy_app") assert app_is_installed(secondary_domain, "legacy_app")
assert not app_is_exposed_on_http(secondary_domain, "/legacy", "This is a dummy app") assert not app_is_exposed_on_http(secondary_domain, "/legacy", "This is a dummy app")
@ -183,11 +192,11 @@ def test_legacy_app_install_private(secondary_domain):
assert app_is_not_installed(secondary_domain, "legacy_app") assert app_is_not_installed(secondary_domain, "legacy_app")
def test_legacy_app_install_unknown_domain(): def test_legacy_app_install_unknown_domain(mocker):
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
with message(mocker, "app_argument_invalid"):
install_legacy_app("whatever.nope", "/legacy") install_legacy_app("whatever.nope", "/legacy")
# TODO check error message
assert app_is_not_installed("whatever.nope", "legacy_app") assert app_is_not_installed("whatever.nope", "legacy_app")
@ -214,55 +223,51 @@ def test_legacy_app_install_multiple_instances(secondary_domain):
assert app_is_not_installed(secondary_domain, "legacy_app__2") assert app_is_not_installed(secondary_domain, "legacy_app__2")
def test_legacy_app_install_path_unavailable(secondary_domain): def test_legacy_app_install_path_unavailable(mocker, secondary_domain):
# These will be removed in teardown # These will be removed in teardown
install_legacy_app(secondary_domain, "/legacy") install_legacy_app(secondary_domain, "/legacy")
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
with message(mocker, "app_location_unavailable"):
install_legacy_app(secondary_domain, "/") install_legacy_app(secondary_domain, "/")
# TODO check error message
assert app_is_installed(secondary_domain, "legacy_app") assert app_is_installed(secondary_domain, "legacy_app")
assert app_is_not_installed(secondary_domain, "legacy_app__2") assert app_is_not_installed(secondary_domain, "legacy_app__2")
def test_legacy_app_install_bad_args(): def test_legacy_app_install_with_nginx_down(mocker, secondary_domain):
with pytest.raises(YunohostError):
install_legacy_app("this.domain.does.not.exists", "/legacy")
def test_legacy_app_install_with_nginx_down(secondary_domain):
os.system("systemctl stop nginx") os.system("systemctl stop nginx")
with pytest.raises(YunohostError): with raiseYunohostError(mocker, "app_action_cannot_be_ran_because_required_services_down"):
install_legacy_app(secondary_domain, "/legacy") install_legacy_app(secondary_domain, "/legacy")
def test_legacy_app_failed_install(secondary_domain): def test_legacy_app_failed_install(mocker, secondary_domain):
# This will conflict with the folder that the app # This will conflict with the folder that the app
# attempts to create, making the install fail # attempts to create, making the install fail
mkdir("/var/www/legacy_app/", 0o750) mkdir("/var/www/legacy_app/", 0o750)
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
with message(mocker, 'app_install_script_failed'):
install_legacy_app(secondary_domain, "/legacy") install_legacy_app(secondary_domain, "/legacy")
# TODO check error message
assert app_is_not_installed(secondary_domain, "legacy_app") assert app_is_not_installed(secondary_domain, "legacy_app")
def test_legacy_app_failed_remove(secondary_domain): def test_legacy_app_failed_remove(mocker, secondary_domain):
install_legacy_app(secondary_domain, "/legacy") install_legacy_app(secondary_domain, "/legacy")
# The remove script runs with set -eu and attempt to remove this # The remove script runs with set -eu and attempt to remove this
# file without -f, so will fail if it's not there ;) # file without -f, so will fail if it's not there ;)
os.remove("/etc/nginx/conf.d/%s.d/%s.conf" % (secondary_domain, "legacy_app")) os.remove("/etc/nginx/conf.d/%s.d/%s.conf" % (secondary_domain, "legacy_app"))
with pytest.raises(YunohostError):
app_remove("legacy") # TODO / FIXME : can't easily validate that 'app_not_properly_removed'
# is triggered for weird reasons ...
app_remove("legacy_app")
# #
# Well here, we hit the classical issue where if an app removal script # Well here, we hit the classical issue where if an app removal script
@ -272,50 +277,68 @@ def test_legacy_app_failed_remove(secondary_domain):
assert app_is_not_installed(secondary_domain, "legacy") assert app_is_not_installed(secondary_domain, "legacy")
def test_systemfuckedup_during_app_install(secondary_domain): def test_full_domain_app(secondary_domain):
install_full_domain_app(secondary_domain)
assert app_is_exposed_on_http(secondary_domain, "/", "This is a dummy app")
def test_full_domain_app_with_conflicts(mocker, secondary_domain):
install_legacy_app(secondary_domain, "/legacy")
with raiseYunohostError(mocker, "app_full_domain_unavailable"):
install_full_domain_app(secondary_domain)
def test_systemfuckedup_during_app_install(mocker, secondary_domain):
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
with message(mocker, "app_install_failed"):
with message(mocker, 'app_action_broke_system'):
install_break_yo_system(secondary_domain, breakwhat="install") install_break_yo_system(secondary_domain, breakwhat="install")
os.system("nginx -t")
os.system("systemctl status nginx")
assert app_is_not_installed(secondary_domain, "break_yo_system") assert app_is_not_installed(secondary_domain, "break_yo_system")
def test_systemfuckedup_during_app_remove(secondary_domain): def test_systemfuckedup_during_app_remove(mocker, secondary_domain):
install_break_yo_system(secondary_domain, breakwhat="remove") install_break_yo_system(secondary_domain, breakwhat="remove")
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
with message(mocker, 'app_action_broke_system'):
with message(mocker, 'app_removed'):
app_remove("break_yo_system") app_remove("break_yo_system")
os.system("nginx -t")
os.system("systemctl status nginx")
assert app_is_not_installed(secondary_domain, "break_yo_system") assert app_is_not_installed(secondary_domain, "break_yo_system")
def test_systemfuckedup_during_app_install_and_remove(secondary_domain): def test_systemfuckedup_during_app_install_and_remove(mocker, secondary_domain):
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
with message(mocker, "app_install_failed"):
with message(mocker, 'app_action_broke_system'):
install_break_yo_system(secondary_domain, breakwhat="everything") install_break_yo_system(secondary_domain, breakwhat="everything")
assert app_is_not_installed(secondary_domain, "break_yo_system") assert app_is_not_installed(secondary_domain, "break_yo_system")
def test_systemfuckedup_during_app_upgrade(secondary_domain): def test_systemfuckedup_during_app_upgrade(mocker, secondary_domain):
install_break_yo_system(secondary_domain, breakwhat="upgrade") install_break_yo_system(secondary_domain, breakwhat="upgrade")
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
with message(mocker, 'app_action_broke_system'):
app_upgrade("break_yo_system", file="./tests/apps/break_yo_system_ynh") app_upgrade("break_yo_system", file="./tests/apps/break_yo_system_ynh")
def test_failed_multiple_app_upgrade(secondary_domain): def test_failed_multiple_app_upgrade(mocker, secondary_domain):
install_legacy_app(secondary_domain, "/legacy") install_legacy_app(secondary_domain, "/legacy")
install_break_yo_system(secondary_domain, breakwhat="upgrade") install_break_yo_system(secondary_domain, breakwhat="upgrade")
with pytest.raises(YunohostError): with raiseYunohostError(mocker, 'app_not_upgraded'):
app_upgrade(["break_yo_system", "legacy_app"], app_upgrade(["break_yo_system", "legacy_app"],
file={"break_yo_system": "./tests/apps/break_yo_system_ynh", file={"break_yo_system": "./tests/apps/break_yo_system_ynh",
"legacy": "./tests/apps/legacy_app_ynh"}) "legacy": "./tests/apps/legacy_app_ynh"})

View file

@ -2,14 +2,13 @@ import pytest
import os import os
import shutil import shutil
import subprocess import subprocess
from mock import ANY
from moulinette import m18n from conftest import message, raiseYunohostError
from yunohost.app import app_install, app_remove, app_ssowatconf from yunohost.app import app_install, app_remove, app_ssowatconf
from yunohost.app import _is_installed from yunohost.app import _is_installed
from yunohost.backup import backup_create, backup_restore, backup_list, backup_info, backup_delete, _recursive_umount from yunohost.backup import backup_create, backup_restore, backup_list, backup_info, backup_delete, _recursive_umount
from yunohost.domain import _get_maindomain from yunohost.domain import _get_maindomain
from yunohost.utils.error import YunohostError
from yunohost.user import user_permission_list, user_create, user_list, user_delete from yunohost.user import user_permission_list, user_create, user_list, user_delete
from yunohost.tests.test_permission import check_LDAP_db_integrity, check_permission_for_apps from yunohost.tests.test_permission import check_LDAP_db_integrity, check_permission_for_apps
@ -206,9 +205,10 @@ def add_archive_system_from_2p4():
# #
def test_backup_only_ldap(): def test_backup_only_ldap(mocker):
# Create the backup # Create the backup
with message(mocker, "backup_created"):
backup_create(system=["conf_ldap"], apps=None) backup_create(system=["conf_ldap"], apps=None)
archives = backup_list()["archives"] archives = backup_list()["archives"]
@ -222,23 +222,21 @@ def test_backup_only_ldap():
def test_backup_system_part_that_does_not_exists(mocker): def test_backup_system_part_that_does_not_exists(mocker):
mocker.spy(m18n, "n")
# Create the backup # Create the backup
with pytest.raises(YunohostError): with message(mocker, 'backup_hook_unknown', hook="doesnt_exist"):
backup_create(system=["yolol"], apps=None) with raiseYunohostError(mocker, "backup_nothings_done"):
backup_create(system=["doesnt_exist"], apps=None)
m18n.n.assert_any_call('backup_hook_unknown', hook="yolol")
m18n.n.assert_any_call('backup_nothings_done')
# #
# System backup and restore # # System backup and restore #
# #
def test_backup_and_restore_all_sys(): def test_backup_and_restore_all_sys(mocker):
# Create the backup # Create the backup
with message(mocker, "backup_created"):
backup_create(system=[], apps=None) backup_create(system=[], apps=None)
archives = backup_list()["archives"] archives = backup_list()["archives"]
@ -255,6 +253,7 @@ def test_backup_and_restore_all_sys():
assert not os.path.exists("/etc/ssowat/conf.json") assert not os.path.exists("/etc/ssowat/conf.json")
# Restore the backup # Restore the backup
with message(mocker, "restore_complete"):
backup_restore(name=archives[0], force=True, backup_restore(name=archives[0], force=True,
system=[], apps=None) system=[], apps=None)
@ -270,12 +269,14 @@ def test_backup_and_restore_all_sys():
def test_restore_system_from_Ynh2p4(monkeypatch, mocker): def test_restore_system_from_Ynh2p4(monkeypatch, mocker):
# Backup current system # Backup current system
with message(mocker, "backup_created"):
backup_create(system=[], apps=None) backup_create(system=[], apps=None)
archives = backup_list()["archives"] archives = backup_list()["archives"]
assert len(archives) == 2 assert len(archives) == 2
# Restore system archive from 2.4 # Restore system archive from 2.4
try: try:
with message(mocker, "restore_complete"):
backup_restore(name=backup_list()["archives"][1], backup_restore(name=backup_list()["archives"][1],
system=[], system=[],
apps=None, apps=None,
@ -306,13 +307,11 @@ def test_backup_script_failure_handling(monkeypatch, mocker):
# call with monkeypatch). We also patch m18n to check later it's been called # call with monkeypatch). We also patch m18n to check later it's been called
# with the expected error message key # with the expected error message key
monkeypatch.setattr("yunohost.backup.hook_exec", custom_hook_exec) monkeypatch.setattr("yunohost.backup.hook_exec", custom_hook_exec)
mocker.spy(m18n, "n")
with pytest.raises(YunohostError): with message(mocker, 'backup_app_failed', app='backup_recommended_app'):
with raiseYunohostError(mocker, 'backup_nothings_done'):
backup_create(system=None, apps=["backup_recommended_app"]) backup_create(system=None, apps=["backup_recommended_app"])
m18n.n.assert_any_call('backup_app_failed', app='backup_recommended_app')
@pytest.mark.with_backup_recommended_app_installed @pytest.mark.with_backup_recommended_app_installed
def test_backup_not_enough_free_space(monkeypatch, mocker): def test_backup_not_enough_free_space(monkeypatch, mocker):
@ -327,26 +326,18 @@ def test_backup_not_enough_free_space(monkeypatch, mocker):
monkeypatch.setattr("yunohost.backup.free_space_in_directory", monkeypatch.setattr("yunohost.backup.free_space_in_directory",
custom_free_space_in_directory) custom_free_space_in_directory)
mocker.spy(m18n, "n") with raiseYunohostError(mocker, 'not_enough_disk_space'):
with pytest.raises(YunohostError):
backup_create(system=None, apps=["backup_recommended_app"]) backup_create(system=None, apps=["backup_recommended_app"])
m18n.n.assert_any_call('not_enough_disk_space', path=ANY)
def test_backup_app_not_installed(mocker): def test_backup_app_not_installed(mocker):
assert not _is_installed("wordpress") assert not _is_installed("wordpress")
mocker.spy(m18n, "n") with message(mocker, "unbackup_app", app="wordpress"):
with raiseYunohostError(mocker, 'backup_nothings_done'):
with pytest.raises(YunohostError):
backup_create(system=None, apps=["wordpress"]) backup_create(system=None, apps=["wordpress"])
m18n.n.assert_any_call("unbackup_app", app="wordpress")
m18n.n.assert_any_call('backup_nothings_done')
@pytest.mark.with_backup_recommended_app_installed @pytest.mark.with_backup_recommended_app_installed
def test_backup_app_with_no_backup_script(mocker): def test_backup_app_with_no_backup_script(mocker):
@ -355,14 +346,10 @@ def test_backup_app_with_no_backup_script(mocker):
os.system("rm %s" % backup_script) os.system("rm %s" % backup_script)
assert not os.path.exists(backup_script) assert not os.path.exists(backup_script)
mocker.spy(m18n, "n") with message(mocker, "backup_with_no_backup_script_for_app", app="backup_recommended_app"):
with raiseYunohostError(mocker, 'backup_nothings_done'):
with pytest.raises(YunohostError):
backup_create(system=None, apps=["backup_recommended_app"]) backup_create(system=None, apps=["backup_recommended_app"])
m18n.n.assert_any_call("backup_with_no_backup_script_for_app", app="backup_recommended_app")
m18n.n.assert_any_call('backup_nothings_done')
@pytest.mark.with_backup_recommended_app_installed @pytest.mark.with_backup_recommended_app_installed
def test_backup_app_with_no_restore_script(mocker): def test_backup_app_with_no_restore_script(mocker):
@ -371,20 +358,18 @@ def test_backup_app_with_no_restore_script(mocker):
os.system("rm %s" % restore_script) os.system("rm %s" % restore_script)
assert not os.path.exists(restore_script) assert not os.path.exists(restore_script)
mocker.spy(m18n, "n")
# Backuping an app with no restore script will only display a warning to the # Backuping an app with no restore script will only display a warning to the
# user... # user...
with message(mocker, "backup_with_no_restore_script_for_app", app="backup_recommended_app"):
backup_create(system=None, apps=["backup_recommended_app"]) backup_create(system=None, apps=["backup_recommended_app"])
m18n.n.assert_any_call("backup_with_no_restore_script_for_app", app="backup_recommended_app")
@pytest.mark.clean_opt_dir @pytest.mark.clean_opt_dir
def test_backup_with_different_output_directory(): def test_backup_with_different_output_directory(mocker):
# Create the backup # Create the backup
with message(mocker, "backup_created"):
backup_create(system=["conf_ssh"], apps=None, backup_create(system=["conf_ssh"], apps=None,
output_directory="/opt/test_backup_output_directory", output_directory="/opt/test_backup_output_directory",
name="backup") name="backup")
@ -401,8 +386,10 @@ def test_backup_with_different_output_directory():
@pytest.mark.clean_opt_dir @pytest.mark.clean_opt_dir
def test_backup_with_no_compress(): def test_backup_with_no_compress(mocker):
# Create the backup # Create the backup
with message(mocker, "backup_created"):
backup_create(system=["conf_nginx"], apps=None, backup_create(system=["conf_nginx"], apps=None,
output_directory="/opt/test_backup_output_directory", output_directory="/opt/test_backup_output_directory",
no_compress=True, no_compress=True,
@ -416,8 +403,9 @@ def test_backup_with_no_compress():
# #
@pytest.mark.with_wordpress_archive_from_2p4 @pytest.mark.with_wordpress_archive_from_2p4
def test_restore_app_wordpress_from_Ynh2p4(): def test_restore_app_wordpress_from_Ynh2p4(mocker):
with message(mocker, "restore_complete"):
backup_restore(system=None, name=backup_list()["archives"][0], backup_restore(system=None, name=backup_list()["archives"][0],
apps=["wordpress"]) apps=["wordpress"])
@ -431,16 +419,14 @@ def test_restore_app_script_failure_handling(monkeypatch, mocker):
raise Exception raise Exception
monkeypatch.setattr("yunohost.backup.hook_exec", custom_hook_exec) monkeypatch.setattr("yunohost.backup.hook_exec", custom_hook_exec)
mocker.spy(m18n, "n")
assert not _is_installed("wordpress") assert not _is_installed("wordpress")
with pytest.raises(YunohostError): with message(mocker, 'restore_app_failed', app='wordpress'):
with raiseYunohostError(mocker, 'restore_nothings_done'):
backup_restore(system=None, name=backup_list()["archives"][0], backup_restore(system=None, name=backup_list()["archives"][0],
apps=["wordpress"]) apps=["wordpress"])
m18n.n.assert_any_call('restore_app_failed', app='wordpress')
m18n.n.assert_any_call('restore_nothings_done')
assert not _is_installed("wordpress") assert not _is_installed("wordpress")
@ -452,18 +438,13 @@ def test_restore_app_not_enough_free_space(monkeypatch, mocker):
monkeypatch.setattr("yunohost.backup.free_space_in_directory", monkeypatch.setattr("yunohost.backup.free_space_in_directory",
custom_free_space_in_directory) custom_free_space_in_directory)
mocker.spy(m18n, "n")
assert not _is_installed("wordpress") assert not _is_installed("wordpress")
with pytest.raises(YunohostError): with raiseYunohostError(mocker, 'restore_not_enough_disk_space'):
backup_restore(system=None, name=backup_list()["archives"][0], backup_restore(system=None, name=backup_list()["archives"][0],
apps=["wordpress"]) apps=["wordpress"])
m18n.n.assert_any_call('restore_not_enough_disk_space',
free_space=0,
margin=ANY,
needed_space=ANY)
assert not _is_installed("wordpress") assert not _is_installed("wordpress")
@ -473,13 +454,11 @@ def test_restore_app_not_in_backup(mocker):
assert not _is_installed("wordpress") assert not _is_installed("wordpress")
assert not _is_installed("yoloswag") assert not _is_installed("yoloswag")
mocker.spy(m18n, "n") with message(mocker, 'backup_archive_app_not_found', app="yoloswag"):
with raiseYunohostError(mocker, 'restore_nothings_done'):
with pytest.raises(YunohostError):
backup_restore(system=None, name=backup_list()["archives"][0], backup_restore(system=None, name=backup_list()["archives"][0],
apps=["yoloswag"]) apps=["yoloswag"])
m18n.n.assert_any_call('backup_archive_app_not_found', app="yoloswag")
assert not _is_installed("wordpress") assert not _is_installed("wordpress")
assert not _is_installed("yoloswag") assert not _is_installed("yoloswag")
@ -489,38 +468,36 @@ def test_restore_app_already_installed(mocker):
assert not _is_installed("wordpress") assert not _is_installed("wordpress")
with message(mocker, "restore_complete"):
backup_restore(system=None, name=backup_list()["archives"][0], backup_restore(system=None, name=backup_list()["archives"][0],
apps=["wordpress"]) apps=["wordpress"])
assert _is_installed("wordpress") assert _is_installed("wordpress")
mocker.spy(m18n, "n") with message(mocker, 'restore_already_installed_app', app="wordpress"):
with pytest.raises(YunohostError): with raiseYunohostError(mocker, 'restore_nothings_done'):
backup_restore(system=None, name=backup_list()["archives"][0], backup_restore(system=None, name=backup_list()["archives"][0],
apps=["wordpress"]) apps=["wordpress"])
m18n.n.assert_any_call('restore_already_installed_app', app="wordpress")
m18n.n.assert_any_call('restore_nothings_done')
assert _is_installed("wordpress") assert _is_installed("wordpress")
@pytest.mark.with_legacy_app_installed @pytest.mark.with_legacy_app_installed
def test_backup_and_restore_legacy_app(): def test_backup_and_restore_legacy_app(mocker):
_test_backup_and_restore_app("legacy_app") _test_backup_and_restore_app(mocker, "legacy_app")
@pytest.mark.with_backup_recommended_app_installed @pytest.mark.with_backup_recommended_app_installed
def test_backup_and_restore_recommended_app(): def test_backup_and_restore_recommended_app(mocker):
_test_backup_and_restore_app("backup_recommended_app") _test_backup_and_restore_app(mocker, "backup_recommended_app")
@pytest.mark.with_backup_recommended_app_installed_with_ynh_restore @pytest.mark.with_backup_recommended_app_installed_with_ynh_restore
def test_backup_and_restore_with_ynh_restore(): def test_backup_and_restore_with_ynh_restore(mocker):
_test_backup_and_restore_app("backup_recommended_app") _test_backup_and_restore_app(mocker, "backup_recommended_app")
@pytest.mark.with_permission_app_installed @pytest.mark.with_permission_app_installed
def test_backup_and_restore_permission_app(): def test_backup_and_restore_permission_app():
@ -529,11 +506,11 @@ def test_backup_and_restore_permission_app():
assert "permissions_app.main" in res assert "permissions_app.main" in res
assert "permissions_app.admin" in res assert "permissions_app.admin" in res
assert "permissions_app.dev" in res assert "permissions_app.dev" in res
assert res['permissions_app.main']['urls'] == [maindomain + "/urlpermissionapp"] assert res['permissions_app.main']['url'] == "/"
assert res['permissions_app.admin']['urls'] == [maindomain + "/urlpermissionapp/admin"] assert res['permissions_app.admin']['url'] == "/admin"
assert res['permissions_app.dev']['urls'] == [maindomain + "/urlpermissionapp/dev"] assert res['permissions_app.dev']['url'] == "/dev"
assert res['permissions_app.main']['allowed'] == ["all_users"] assert res['permissions_app.main']['allowed'] == ["visitors"]
assert res['permissions_app.admin']['allowed'] == ["alice"] assert res['permissions_app.admin']['allowed'] == ["alice"]
assert res['permissions_app.dev']['allowed'] == [] assert res['permissions_app.dev']['allowed'] == []
@ -543,18 +520,19 @@ def test_backup_and_restore_permission_app():
assert "permissions_app.main" in res assert "permissions_app.main" in res
assert "permissions_app.admin" in res assert "permissions_app.admin" in res
assert "permissions_app.dev" in res assert "permissions_app.dev" in res
assert res['permissions_app.main']['urls'] == [maindomain + "/urlpermissionapp"] assert res['permissions_app.main']['url'] == "/"
assert res['permissions_app.admin']['urls'] == [maindomain + "/urlpermissionapp/admin"] assert res['permissions_app.admin']['url'] == "/admin"
assert res['permissions_app.dev']['urls'] == [maindomain + "/urlpermissionapp/dev"] assert res['permissions_app.dev']['url'] == "/dev"
assert res['permissions_app.main']['allowed'] == ["all_users"] assert res['permissions_app.main']['allowed'] == ["visitors"]
assert res['permissions_app.admin']['allowed'] == ["alice"] assert res['permissions_app.admin']['allowed'] == ["alice"]
assert res['permissions_app.dev']['allowed'] == [] assert res['permissions_app.dev']['allowed'] == []
def _test_backup_and_restore_app(app): def _test_backup_and_restore_app(mocker, app):
# Create a backup of this app # Create a backup of this app
with message(mocker, "backup_created"):
backup_create(system=None, apps=[app]) backup_create(system=None, apps=[app])
archives = backup_list()["archives"] archives = backup_list()["archives"]
@ -571,6 +549,7 @@ def _test_backup_and_restore_app(app):
assert app+".main" not in user_permission_list()['permissions'] assert app+".main" not in user_permission_list()['permissions']
# Restore the app # Restore the app
with message(mocker, "restore_complete"):
backup_restore(system=None, name=archives[0], backup_restore(system=None, name=archives[0],
apps=[app]) apps=[app])
@ -593,13 +572,11 @@ def test_restore_archive_with_no_json(mocker):
assert "badbackup" in backup_list()["archives"] assert "badbackup" in backup_list()["archives"]
mocker.spy(m18n, "n") with raiseYunohostError(mocker, 'backup_invalid_archive'):
with pytest.raises(YunohostError):
backup_restore(name="badbackup", force=True) backup_restore(name="badbackup", force=True)
m18n.n.assert_any_call('backup_invalid_archive')
def test_backup_binds_are_readonly(monkeypatch): def test_backup_binds_are_readonly(mocker, monkeypatch):
def custom_mount_and_backup(self, backup_manager): def custom_mount_and_backup(self, backup_manager):
self.manager = backup_manager self.manager = backup_manager
@ -620,4 +597,5 @@ def test_backup_binds_are_readonly(monkeypatch):
custom_mount_and_backup) custom_mount_and_backup)
# Create the backup # Create the backup
with message(mocker, "backup_created"):
backup_create(system=[]) backup_create(system=[])

View file

@ -1,44 +1,54 @@
import requests
import pytest import pytest
from yunohost.app import app_install, app_remove, app_change_url, app_list, app_map from conftest import message, raiseYunohostError
from yunohost.user import user_list, user_info, user_create, user_delete, user_update, \ from yunohost.app import app_install, app_remove, app_change_url, app_list, app_map
user_group_list, user_group_create, user_group_delete, user_group_update, user_group_info from yunohost.user import user_list, user_create, user_delete, \
user_group_list, user_group_delete
from yunohost.permission import user_permission_update, user_permission_list, user_permission_reset, \ from yunohost.permission import user_permission_update, user_permission_list, user_permission_reset, \
permission_create, permission_urls, permission_delete permission_create, permission_delete, permission_url
from yunohost.domain import _get_maindomain from yunohost.domain import _get_maindomain
from yunohost.utils.error import YunohostError
# Get main domain # Get main domain
maindomain = _get_maindomain() maindomain = _get_maindomain()
dummy_password = "test123Ynh"
def clean_user_groups_permission(): def clean_user_groups_permission():
for u in user_list()['users']: for u in user_list()['users']:
user_delete(u) user_delete(u)
for g in user_group_list()['groups']: for g in user_group_list()['groups']:
if g != "all_users": if g not in ["all_users", "visitors"]:
user_group_delete(g) user_group_delete(g)
for p in user_permission_list()['permissions']: for p in user_permission_list()['permissions']:
if any(p.startswith(name) for name in ["wiki", "blog", "site", "permissions_app"]): if any(p.startswith(name) for name in ["wiki", "blog", "site", "permissions_app"]):
permission_delete(p, force=True, sync_perm=False) permission_delete(p, force=True, sync_perm=False)
def setup_function(function): def setup_function(function):
clean_user_groups_permission() clean_user_groups_permission()
user_create("alice", "Alice", "White", "alice@" + maindomain, "test123Ynh") user_create("alice", "Alice", "White", "alice@" + maindomain, dummy_password)
user_create("bob", "Bob", "Snow", "bob@" + maindomain, "test123Ynh") user_create("bob", "Bob", "Snow", "bob@" + maindomain, dummy_password)
permission_create("wiki.main", urls=[maindomain + "/wiki"], sync_perm=False) permission_create("wiki.main", url="/", sync_perm=False)
permission_create("blog.main", sync_perm=False) permission_create("blog.main", sync_perm=False)
user_permission_update("blog.main", remove="all_users", add="alice") user_permission_update("blog.main", remove="all_users", add="alice")
def teardown_function(function): def teardown_function(function):
clean_user_groups_permission() clean_user_groups_permission()
try: try:
app_remove("permissions_app") app_remove("permissions_app")
except: except:
pass pass
try:
app_remove("legacy_app")
except:
pass
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def check_LDAP_db_integrity_call(): def check_LDAP_db_integrity_call():
@ -46,6 +56,7 @@ def check_LDAP_db_integrity_call():
yield yield
check_LDAP_db_integrity() check_LDAP_db_integrity()
def check_LDAP_db_integrity(): def check_LDAP_db_integrity():
# Here we check that all attributes in all object are sychronized. # Here we check that all attributes in all object are sychronized.
# Here is the list of attributes per object: # Here is the list of attributes per object:
@ -156,6 +167,32 @@ def check_permission_for_apps():
assert installed_apps == app_perms_prefix assert installed_apps == app_perms_prefix
def can_access_webpage(webpath, logged_as=None):
webpath = webpath.rstrip("/")
sso_url = "https://" + maindomain + "/yunohost/sso/"
# Anonymous access
if not logged_as:
r = requests.get(webpath, verify=False)
# Login as a user using dummy password
else:
with requests.Session() as session:
session.post(sso_url,
data={"user": logged_as,
"password": dummy_password},
headers={"Referer": sso_url,
"Content-Type": "application/x-www-form-urlencoded"},
verify=False)
# We should have some cookies related to authentication now
assert session.cookies
r = session.get(webpath, verify=False)
# If we can't access it, we got redirected to the SSO
return not r.url.startswith(sso_url)
# #
# List functions # List functions
# #
@ -171,13 +208,15 @@ def test_permission_list():
assert res['blog.main']['allowed'] == ["alice"] assert res['blog.main']['allowed'] == ["alice"]
assert set(res['wiki.main']['corresponding_users']) == set(["alice", "bob"]) assert set(res['wiki.main']['corresponding_users']) == set(["alice", "bob"])
assert res['blog.main']['corresponding_users'] == ["alice"] assert res['blog.main']['corresponding_users'] == ["alice"]
assert res['wiki.main']['urls'] == [maindomain + "/wiki"] assert res['wiki.main']['url'] == "/"
# #
# Create - Remove functions # Create - Remove functions
# #
def test_permission_create_main():
def test_permission_create_main(mocker):
with message(mocker, "permission_created", permission="site.main"):
permission_create("site.main") permission_create("site.main")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
@ -186,7 +225,8 @@ def test_permission_create_main():
assert set(res['site.main']['corresponding_users']) == set(["alice", "bob"]) assert set(res['site.main']['corresponding_users']) == set(["alice", "bob"])
def test_permission_create_extra(): def test_permission_create_extra(mocker):
with message(mocker, "permission_created", permission="site.test"):
permission_create("site.test") permission_create("site.test")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
@ -195,7 +235,17 @@ def test_permission_create_extra():
assert "all_users" not in res['site.test']['allowed'] assert "all_users" not in res['site.test']['allowed']
assert res['site.test']['corresponding_users'] == [] assert res['site.test']['corresponding_users'] == []
def test_permission_delete():
def test_permission_create_with_allowed():
permission_create("site.test", allowed=["alice"])
res = user_permission_list(full=True)['permissions']
assert "site.test" in res
assert res['site.test']['allowed'] == ["alice"]
def test_permission_delete(mocker):
with message(mocker, "permission_deleted", permission="wiki.main"):
permission_delete("wiki.main", force=True) permission_delete("wiki.main", force=True)
res = user_permission_list()['permissions'] res = user_permission_list()['permissions']
@ -205,12 +255,14 @@ def test_permission_delete():
# Error on create - remove function # Error on create - remove function
# #
def test_permission_create_already_existing():
with pytest.raises(YunohostError): def test_permission_create_already_existing(mocker):
with raiseYunohostError(mocker, "permission_already_exist"):
permission_create("wiki.main") permission_create("wiki.main")
def test_permission_delete_doesnt_existing():
with pytest.raises(YunohostError): def test_permission_delete_doesnt_existing(mocker):
with raiseYunohostError(mocker, "permission_not_found"):
permission_delete("doesnt.exist", force=True) permission_delete("doesnt.exist", force=True)
res = user_permission_list()['permissions'] res = user_permission_list()['permissions']
@ -219,8 +271,9 @@ def test_permission_delete_doesnt_existing():
assert "mail.main" in res assert "mail.main" in res
assert "xmpp.main" in res assert "xmpp.main" in res
def test_permission_delete_main_without_force():
with pytest.raises(YunohostError): def test_permission_delete_main_without_force(mocker):
with raiseYunohostError(mocker, "permission_cannot_remove_main"):
permission_delete("blog.main") permission_delete("blog.main")
res = user_permission_list()['permissions'] res = user_permission_list()['permissions']
@ -232,116 +285,130 @@ def test_permission_delete_main_without_force():
# user side functions # user side functions
def test_permission_add_group():
def test_permission_add_group(mocker):
with message(mocker, "permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", add="alice") user_permission_update("wiki.main", add="alice")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert set(res['wiki.main']['allowed']) == set(["all_users", "alice"]) assert set(res['wiki.main']['allowed']) == set(["all_users", "alice"])
assert set(res['wiki.main']['corresponding_users']) == set(["alice", "bob"]) assert set(res['wiki.main']['corresponding_users']) == set(["alice", "bob"])
def test_permission_remove_group():
def test_permission_remove_group(mocker):
with message(mocker, "permission_updated", permission="blog.main"):
user_permission_update("blog.main", remove="alice") user_permission_update("blog.main", remove="alice")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res['blog.main']['allowed'] == [] assert res['blog.main']['allowed'] == []
assert res['blog.main']['corresponding_users'] == [] assert res['blog.main']['corresponding_users'] == []
def test_permission_add_and_remove_group():
def test_permission_add_and_remove_group(mocker):
with message(mocker, "permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", add="alice", remove="all_users") user_permission_update("wiki.main", add="alice", remove="all_users")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res['wiki.main']['allowed'] == ["alice"] assert res['wiki.main']['allowed'] == ["alice"]
assert res['wiki.main']['corresponding_users'] == ["alice"] assert res['wiki.main']['corresponding_users'] == ["alice"]
def test_permission_add_group_already_allowed():
def test_permission_add_group_already_allowed(mocker):
with message(mocker, "permission_already_allowed", permission="blog.main", group="alice"):
user_permission_update("blog.main", add="alice") user_permission_update("blog.main", add="alice")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res['blog.main']['allowed'] == ["alice"] assert res['blog.main']['allowed'] == ["alice"]
assert res['blog.main']['corresponding_users'] == ["alice"] assert res['blog.main']['corresponding_users'] == ["alice"]
def test_permission_remove_group_already_not_allowed():
def test_permission_remove_group_already_not_allowed(mocker):
with message(mocker, "permission_already_disallowed", permission="blog.main", group="bob"):
user_permission_update("blog.main", remove="bob") user_permission_update("blog.main", remove="bob")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res['blog.main']['allowed'] == ["alice"] assert res['blog.main']['allowed'] == ["alice"]
assert res['blog.main']['corresponding_users'] == ["alice"] assert res['blog.main']['corresponding_users'] == ["alice"]
def test_permission_reset():
# Reset permission def test_permission_reset(mocker):
with message(mocker, "permission_updated", permission="blog.main"):
user_permission_reset("blog.main") user_permission_reset("blog.main")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res['blog.main']['allowed'] == ["all_users"] assert res['blog.main']['allowed'] == ["all_users"]
assert set(res['blog.main']['corresponding_users']) == set(["alice", "bob"]) assert set(res['blog.main']['corresponding_users']) == set(["alice", "bob"])
def test_permission_reset_idempotency():
# Reset permission
user_permission_reset("blog.main")
user_permission_reset("blog.main")
res = user_permission_list(full=True)['permissions']
assert res['blog.main']['allowed'] == ["all_users"]
assert set(res['blog.main']['corresponding_users']) == set(["alice", "bob"])
def test_permission_reset_idempotency():
# Reset permission
user_permission_reset("blog.main")
user_permission_reset("blog.main")
res = user_permission_list(full=True)['permissions']
assert res['blog.main']['allowed'] == ["all_users"]
assert set(res['blog.main']['corresponding_users']) == set(["alice", "bob"])
# #
# Error on update function # Error on update function
# #
def test_permission_add_group_that_doesnt_exist():
with pytest.raises(YunohostError): def test_permission_add_group_that_doesnt_exist(mocker):
with raiseYunohostError(mocker, "group_unknown"):
user_permission_update("blog.main", add="doesnt_exist") user_permission_update("blog.main", add="doesnt_exist")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res['blog.main']['allowed'] == ["alice"] assert res['blog.main']['allowed'] == ["alice"]
assert res['blog.main']['corresponding_users'] == ["alice"] assert res['blog.main']['corresponding_users'] == ["alice"]
def test_permission_update_permission_that_doesnt_exist():
with pytest.raises(YunohostError): def test_permission_update_permission_that_doesnt_exist(mocker):
with raiseYunohostError(mocker, "permission_not_found"):
user_permission_update("doesnt.exist", add="alice") user_permission_update("doesnt.exist", add="alice")
# Permission url management # Permission url management
def test_permission_add_url(): def test_permission_redefine_url():
permission_urls("blog.main", add=[maindomain + "/testA"]) permission_url("blog.main", url="/pwet")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res["blog.main"]["urls"] == [maindomain + "/testA"] assert res["blog.main"]["url"] == "/pwet"
def test_permission_add_second_url():
permission_urls("wiki.main", add=[maindomain + "/testA"])
res = user_permission_list(full=True)['permissions']
assert set(res["wiki.main"]["urls"]) == set([maindomain + "/testA", maindomain + "/wiki"])
def test_permission_remove_url(): def test_permission_remove_url():
permission_urls("wiki.main", remove=[maindomain + "/wiki"]) permission_url("blog.main", url=None)
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res["wiki.main"]["urls"] == [] assert res["blog.main"]["url"] is None
def test_permission_add_url_already_added():
res = user_permission_list(full=True)['permissions']
assert res["wiki.main"]["urls"] == [maindomain + "/wiki"]
permission_urls("wiki.main", add=[maindomain + "/wiki"])
res = user_permission_list(full=True)['permissions']
assert res["wiki.main"]["urls"] == [maindomain + "/wiki"]
def test_permission_remove_url_not_added():
permission_urls("wiki.main", remove=[maindomain + "/doesnt_exist"])
res = user_permission_list(full=True)['permissions']
assert res['wiki.main']['urls'] == [maindomain + "/wiki"]
# #
# Application interaction # Application interaction
# #
def test_permission_app_install(): def test_permission_app_install():
app_install("./tests/apps/permissions_app_ynh", app_install("./tests/apps/permissions_app_ynh",
args="domain=%s&path=%s&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True) args="domain=%s&path=%s&is_public=0&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True)
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert "permissions_app.main" in res assert "permissions_app.main" in res
assert "permissions_app.admin" in res assert "permissions_app.admin" in res
assert "permissions_app.dev" in res assert "permissions_app.dev" in res
assert res['permissions_app.main']['urls'] == [maindomain + "/urlpermissionapp"] assert res['permissions_app.main']['url'] == "/"
assert res['permissions_app.admin']['urls'] == [maindomain + "/urlpermissionapp/admin"] assert res['permissions_app.admin']['url'] == "/admin"
assert res['permissions_app.dev']['urls'] == [maindomain + "/urlpermissionapp/dev"] assert res['permissions_app.dev']['url'] == "/dev"
assert res['permissions_app.main']['allowed'] == ["all_users"] assert res['permissions_app.main']['allowed'] == ["all_users"]
assert set(res['permissions_app.main']['corresponding_users']) == set(["alice", "bob"]) assert set(res['permissions_app.main']['corresponding_users']) == set(["alice", "bob"])
@ -361,25 +428,79 @@ def test_permission_app_install():
def test_permission_app_remove(): def test_permission_app_remove():
app_install("./tests/apps/permissions_app_ynh", app_install("./tests/apps/permissions_app_ynh",
args="domain=%s&path=%s&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True) args="domain=%s&path=%s&is_public=0&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True)
app_remove("permissions_app") app_remove("permissions_app")
# Check all permissions for this app got deleted # Check all permissions for this app got deleted
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert not any(p.startswith("permissions_app.") for p in res.keys()) assert not any(p.startswith("permissions_app.") for p in res.keys())
def test_permission_app_change_url(): def test_permission_app_change_url():
app_install("./tests/apps/permissions_app_ynh", app_install("./tests/apps/permissions_app_ynh",
args="domain=%s&path=%s&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True) args="domain=%s&path=%s&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True)
# FIXME : should rework this test to look for differences in the generated app map / app tiles ...
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res['permissions_app.main']['urls'] == [maindomain + "/urlpermissionapp"] assert res['permissions_app.main']['url'] == "/"
assert res['permissions_app.admin']['urls'] == [maindomain + "/urlpermissionapp/admin"] assert res['permissions_app.admin']['url'] == "/admin"
assert res['permissions_app.dev']['urls'] == [maindomain + "/urlpermissionapp/dev"] assert res['permissions_app.dev']['url'] == "/dev"
app_change_url("permissions_app", maindomain, "/newchangeurl") app_change_url("permissions_app", maindomain, "/newchangeurl")
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res['permissions_app.main']['urls'] == [maindomain + "/newchangeurl"] assert res['permissions_app.main']['url'] == "/"
assert res['permissions_app.admin']['urls'] == [maindomain + "/newchangeurl/admin"] assert res['permissions_app.admin']['url'] == "/admin"
assert res['permissions_app.dev']['urls'] == [maindomain + "/newchangeurl/dev"] assert res['permissions_app.dev']['url'] == "/dev"
def test_permission_app_propagation_on_ssowat():
app_install("./tests/apps/permissions_app_ynh",
args="domain=%s&path=%s&is_public=1&admin=%s" % (maindomain, "/urlpermissionapp", "alice"), force=True)
res = user_permission_list(full=True)['permissions']
assert res['permissions_app.main']['allowed'] == ["visitors"]
app_webroot = "https://%s/urlpermissionapp" % maindomain
assert can_access_webpage(app_webroot, logged_as=None)
assert can_access_webpage(app_webroot, logged_as="alice")
user_permission_update("permissions_app.main", remove="visitors", add="bob")
res = user_permission_list(full=True)['permissions']
assert not can_access_webpage(app_webroot, logged_as=None)
assert not can_access_webpage(app_webroot, logged_as="alice")
assert can_access_webpage(app_webroot, logged_as="bob")
# Test admin access, as configured during install, only alice should be able to access it
# alice gotta be allowed on the main permission to access the admin tho
user_permission_update("permissions_app.main", remove="bob", add="all_users")
assert not can_access_webpage(app_webroot+"/admin", logged_as=None)
assert can_access_webpage(app_webroot+"/admin", logged_as="alice")
assert not can_access_webpage(app_webroot+"/admin", logged_as="bob")
def test_permission_legacy_app_propagation_on_ssowat():
app_install("./tests/apps/legacy_app_ynh",
args="domain=%s&path=%s" % (maindomain, "/legacy"), force=True)
# App is configured as public by default using the legacy unprotected_uri mechanics
# It should automatically be migrated during the install
res = user_permission_list(full=True)['permissions']
assert res['legacy_app.main']['allowed'] == ["visitors"]
app_webroot = "https://%s/legacy" % maindomain
assert can_access_webpage(app_webroot, logged_as=None)
assert can_access_webpage(app_webroot, logged_as="alice")
# Try to update the permission and check that permissions are still consistent
user_permission_update("legacy_app.main", remove="visitors", add="bob")
assert not can_access_webpage(app_webroot, logged_as=None)
assert not can_access_webpage(app_webroot, logged_as="alice")
assert can_access_webpage(app_webroot, logged_as="bob")

View file

@ -1,22 +1,25 @@
import pytest import pytest
from conftest import message, raiseYunohostError
from yunohost.user import user_list, user_info, user_create, user_delete, user_update, \ from yunohost.user import user_list, user_info, user_create, user_delete, user_update, \
user_group_list, user_group_create, user_group_delete, user_group_update, user_group_info user_group_list, user_group_create, user_group_delete, user_group_update
from yunohost.domain import _get_maindomain from yunohost.domain import _get_maindomain
from yunohost.utils.error import YunohostError
from yunohost.tests.test_permission import check_LDAP_db_integrity from yunohost.tests.test_permission import check_LDAP_db_integrity
# Get main domain # Get main domain
maindomain = _get_maindomain() maindomain = _get_maindomain()
def clean_user_groups(): def clean_user_groups():
for u in user_list()['users']: for u in user_list()['users']:
user_delete(u) user_delete(u)
for g in user_group_list()['groups']: for g in user_group_list()['groups']:
if g != "all_users": if g not in ["all_users", "visitors"]:
user_group_delete(g) user_group_delete(g)
def setup_function(function): def setup_function(function):
clean_user_groups() clean_user_groups()
@ -29,9 +32,11 @@ def setup_function(function):
user_group_update("dev", add=["alice"]) user_group_update("dev", add=["alice"])
user_group_update("apps", add=["bob"]) user_group_update("apps", add=["bob"])
def teardown_function(function): def teardown_function(function):
clean_user_groups() clean_user_groups()
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def check_LDAP_db_integrity_call(): def check_LDAP_db_integrity_call():
check_LDAP_db_integrity() check_LDAP_db_integrity()
@ -42,6 +47,7 @@ def check_LDAP_db_integrity_call():
# List functions # List functions
# #
def test_list_users(): def test_list_users():
res = user_list()['users'] res = user_list()['users']
@ -49,6 +55,7 @@ def test_list_users():
assert "bob" in res assert "bob" in res
assert "jack" in res assert "jack" in res
def test_list_groups(): def test_list_groups():
res = user_group_list()['groups'] res = user_group_list()['groups']
@ -65,7 +72,10 @@ def test_list_groups():
# Create - Remove functions # Create - Remove functions
# #
def test_create_user():
def test_create_user(mocker):
with message(mocker, "user_created"):
user_create("albert", "Albert", "Good", "alber@" + maindomain, "test123Ynh") user_create("albert", "Albert", "Good", "alber@" + maindomain, "test123Ynh")
group_res = user_group_list()['groups'] group_res = user_group_list()['groups']
@ -74,7 +84,10 @@ def test_create_user():
assert "albert" in group_res['albert']['members'] assert "albert" in group_res['albert']['members']
assert "albert" in group_res['all_users']['members'] assert "albert" in group_res['all_users']['members']
def test_del_user():
def test_del_user(mocker):
with message(mocker, "user_deleted"):
user_delete("alice") user_delete("alice")
group_res = user_group_list()['groups'] group_res = user_group_list()['groups']
@ -82,7 +95,10 @@ def test_del_user():
assert "alice" not in group_res assert "alice" not in group_res
assert "alice" not in group_res['all_users']['members'] assert "alice" not in group_res['all_users']['members']
def test_create_group():
def test_create_group(mocker):
with message(mocker, "group_created", group="adminsys"):
user_group_create("adminsys") user_group_create("adminsys")
group_res = user_group_list()['groups'] group_res = user_group_list()['groups']
@ -90,7 +106,10 @@ def test_create_group():
assert "members" in group_res['adminsys'].keys() assert "members" in group_res['adminsys'].keys()
assert group_res["adminsys"]["members"] == [] assert group_res["adminsys"]["members"] == []
def test_del_group():
def test_del_group(mocker):
with message(mocker, "group_deleted", group="dev"):
user_group_delete("dev") user_group_delete("dev")
group_res = user_group_list()['groups'] group_res = user_group_list()['groups']
@ -100,74 +119,93 @@ def test_del_group():
# Error on create / remove function # Error on create / remove function
# #
def test_create_user_with_mail_address_already_taken():
with pytest.raises(YunohostError): def test_create_user_with_mail_address_already_taken(mocker):
with raiseYunohostError(mocker, "user_creation_failed"):
user_create("alice2", "Alice", "White", "alice@" + maindomain, "test123Ynh") user_create("alice2", "Alice", "White", "alice@" + maindomain, "test123Ynh")
def test_create_user_with_password_too_simple():
with pytest.raises(YunohostError): def test_create_user_with_password_too_simple(mocker):
with raiseYunohostError(mocker, "password_listed"):
user_create("other", "Alice", "White", "other@" + maindomain, "12") user_create("other", "Alice", "White", "other@" + maindomain, "12")
def test_create_user_already_exists():
with pytest.raises(YunohostError): def test_create_user_already_exists(mocker):
with raiseYunohostError(mocker, "user_already_exists"):
user_create("alice", "Alice", "White", "other@" + maindomain, "test123Ynh") user_create("alice", "Alice", "White", "other@" + maindomain, "test123Ynh")
def test_update_user_with_mail_address_already_taken():
with pytest.raises(YunohostError): def test_update_user_with_mail_address_already_taken(mocker):
with raiseYunohostError(mocker, "user_update_failed"):
user_update("bob", add_mailalias="alice@" + maindomain) user_update("bob", add_mailalias="alice@" + maindomain)
def test_del_user_that_does_not_exist():
with pytest.raises(YunohostError): def test_del_user_that_does_not_exist(mocker):
with raiseYunohostError(mocker, "user_unknown"):
user_delete("doesnt_exist") user_delete("doesnt_exist")
def test_create_group_all_users():
def test_create_group_all_users(mocker):
# Check groups already exist with special group "all_users" # Check groups already exist with special group "all_users"
with pytest.raises(YunohostError): with raiseYunohostError(mocker, "group_already_exist"):
user_group_create("all_users") user_group_create("all_users")
def test_create_group_already_exists():
def test_create_group_already_exists(mocker):
# Check groups already exist (regular groups) # Check groups already exist (regular groups)
with pytest.raises(YunohostError): with raiseYunohostError(mocker, "group_already_exist"):
user_group_create("dev") user_group_create("dev")
def test_del_group_all_users():
with pytest.raises(YunohostError): def test_del_group_all_users(mocker):
with raiseYunohostError(mocker, "group_cannot_be_deleted"):
user_group_delete("all_users") user_group_delete("all_users")
def test_del_group_that_does_not_exist():
with pytest.raises(YunohostError): def test_del_group_that_does_not_exist(mocker):
with raiseYunohostError(mocker, "group_unknown"):
user_group_delete("doesnt_exist") user_group_delete("doesnt_exist")
# #
# Update function # Update function
# #
def test_update_user():
def test_update_user(mocker):
with message(mocker, "user_updated"):
user_update("alice", firstname="NewName", lastname="NewLast") user_update("alice", firstname="NewName", lastname="NewLast")
info = user_info("alice") info = user_info("alice")
assert info['firstname'] == "NewName" assert info['firstname'] == "NewName"
assert info['lastname'] == "NewLast" assert info['lastname'] == "NewLast"
def test_update_group_add_user():
def test_update_group_add_user(mocker):
with message(mocker, "group_updated", group="dev"):
user_group_update("dev", add=["bob"]) user_group_update("dev", add=["bob"])
group_res = user_group_list()['groups'] group_res = user_group_list()['groups']
assert set(group_res['dev']['members']) == set(["alice", "bob"]) assert set(group_res['dev']['members']) == set(["alice", "bob"])
def test_update_group_add_user_already_in():
def test_update_group_add_user_already_in(mocker):
with message(mocker, "group_user_already_in_group", user="bob", group="apps"):
user_group_update("apps", add=["bob"]) user_group_update("apps", add=["bob"])
group_res = user_group_list()['groups'] group_res = user_group_list()['groups']
assert group_res['apps']['members'] == ["bob"] assert group_res['apps']['members'] == ["bob"]
def test_update_group_remove_user():
def test_update_group_remove_user(mocker):
with message(mocker, "group_updated", group="apps"):
user_group_update("apps", remove=["bob"]) user_group_update("apps", remove=["bob"])
group_res = user_group_list()['groups'] group_res = user_group_list()['groups']
assert group_res['apps']['members'] == [] assert group_res['apps']['members'] == []
def test_update_group_remove_user_not_already_in():
def test_update_group_remove_user_not_already_in(mocker):
with message(mocker, "group_user_not_in_group", user="jack", group="apps"):
user_group_update("apps", remove=["jack"]) user_group_update("apps", remove=["jack"])
group_res = user_group_list()['groups'] group_res = user_group_list()['groups']
@ -177,29 +215,33 @@ def test_update_group_remove_user_not_already_in():
# Error on update functions # Error on update functions
# #
def test_update_user_that_doesnt_exist():
with pytest.raises(YunohostError): def test_update_user_that_doesnt_exist(mocker):
with raiseYunohostError(mocker, "user_unknown"):
user_update("doesnt_exist", firstname="NewName", lastname="NewLast") user_update("doesnt_exist", firstname="NewName", lastname="NewLast")
def test_update_group_that_doesnt_exist():
# Check groups not found def test_update_group_that_doesnt_exist(mocker):
with pytest.raises(YunohostError): with raiseYunohostError(mocker, "group_unknown"):
user_group_update("doesnt_exist", add=["alice"]) user_group_update("doesnt_exist", add=["alice"])
def test_update_group_all_users_manually():
with pytest.raises(YunohostError): def test_update_group_all_users_manually(mocker):
with raiseYunohostError(mocker, "group_cannot_edit_all_users"):
user_group_update("all_users", remove=["alice"]) user_group_update("all_users", remove=["alice"])
assert "alice" in user_group_list()["groups"]["all_users"]["members"] assert "alice" in user_group_list()["groups"]["all_users"]["members"]
def test_update_group_primary_manually():
with pytest.raises(YunohostError): def test_update_group_primary_manually(mocker):
with raiseYunohostError(mocker, "group_cannot_edit_primary_group"):
user_group_update("alice", remove=["alice"]) user_group_update("alice", remove=["alice"])
assert "alice" in user_group_list()["groups"]["alice"]["members"] assert "alice" in user_group_list()["groups"]["alice"]["members"]
def test_update_group_add_user_that_doesnt_exist():
# Check add bad user in group def test_update_group_add_user_that_doesnt_exist(mocker):
with pytest.raises(YunohostError): with raiseYunohostError(mocker, "user_unknown"):
user_group_update("dev", add=["doesnt_exist"]) user_group_update("dev", add=["doesnt_exist"])
assert "doesnt_exist" not in user_group_list()["groups"]["dev"]["members"] assert "doesnt_exist" not in user_group_list()["groups"]["dev"]["members"]

View file

@ -301,25 +301,17 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False,
os.system('hostname yunohost.yunohost.org') os.system('hostname yunohost.yunohost.org')
# Add a temporary SSOwat rule to redirect SSO to admin page # Add a temporary SSOwat rule to redirect SSO to admin page
try: if not os.path.exists('/etc/ssowat/conf.json.persistent'):
with open('/etc/ssowat/conf.json.persistent') as json_conf:
ssowat_conf = json.loads(str(json_conf.read()))
except ValueError as e:
raise YunohostError('ssowat_persistent_conf_read_error', error=str(e))
except IOError:
ssowat_conf = {} ssowat_conf = {}
else:
ssowat_conf = read_json('/etc/ssowat/conf.json.persistent')
if 'redirected_urls' not in ssowat_conf: if 'redirected_urls' not in ssowat_conf:
ssowat_conf['redirected_urls'] = {} ssowat_conf['redirected_urls'] = {}
ssowat_conf['redirected_urls']['/'] = domain + '/yunohost/admin' ssowat_conf['redirected_urls']['/'] = domain + '/yunohost/admin'
try: write_to_json('/etc/ssowat/conf.json.persistent', ssowat_conf)
with open('/etc/ssowat/conf.json.persistent', 'w+') as f:
json.dump(ssowat_conf, f, sort_keys=True, indent=4)
except IOError as e:
raise YunohostError('ssowat_persistent_conf_write_error', error=str(e))
os.system('chmod 644 /etc/ssowat/conf.json.persistent') os.system('chmod 644 /etc/ssowat/conf.json.persistent')
# Create SSL CA # Create SSL CA
@ -567,8 +559,8 @@ def tools_upgrade(operation_logger, apps=None, system=False):
# randomly from yunohost itself... upgrading them is likely to # randomly from yunohost itself... upgrading them is likely to
critical_packages = ("moulinette", "yunohost", "yunohost-admin", "ssowat", "python") critical_packages = ("moulinette", "yunohost", "yunohost-admin", "ssowat", "python")
critical_packages_upgradable = [p for p in upgradables if p["name"] in critical_packages] critical_packages_upgradable = [p["name"] for p in upgradables if p["name"] in critical_packages]
noncritical_packages_upgradable = [p for p in upgradables if p["name"] not in critical_packages] noncritical_packages_upgradable = [p["name"] for p in upgradables if p["name"] not in critical_packages]
# Prepare dist-upgrade command # Prepare dist-upgrade command
dist_upgrade = "DEBIAN_FRONTEND=noninteractive" dist_upgrade = "DEBIAN_FRONTEND=noninteractive"
@ -599,8 +591,11 @@ def tools_upgrade(operation_logger, apps=None, system=False):
logger.debug("Running apt command :\n{}".format(dist_upgrade)) logger.debug("Running apt command :\n{}".format(dist_upgrade))
def is_relevant(l):
return "Reading database ..." not in l.rstrip()
callbacks = ( callbacks = (
lambda l: logger.info("+" + l.rstrip() + "\r"), lambda l: logger.info("+ " + l.rstrip() + "\r") if is_relevant(l) else logger.debug(l.rstrip() + "\r"),
lambda l: logger.warning(l.rstrip()), lambda l: logger.warning(l.rstrip()),
) )
returncode = call_async_output(dist_upgrade, callbacks, shell=True) returncode = call_async_output(dist_upgrade, callbacks, shell=True)

View file

@ -35,8 +35,10 @@ import subprocess
import copy import copy
from moulinette import m18n from moulinette import m18n
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import read_json, write_to_json, read_yaml, write_to_yaml
from yunohost.utils.error import YunohostError
from yunohost.service import service_status from yunohost.service import service_status
from yunohost.log import is_unit_operation from yunohost.log import is_unit_operation
@ -195,21 +197,16 @@ def user_create(operation_logger, username, firstname, lastname, mail, password,
attr_dict['mail'] = [attr_dict['mail']] + aliases attr_dict['mail'] = [attr_dict['mail']] + aliases
# If exists, remove the redirection from the SSO # If exists, remove the redirection from the SSO
try: if not os.path.exists('/etc/ssowat/conf.json.persistent'):
with open('/etc/ssowat/conf.json.persistent') as json_conf:
ssowat_conf = json.loads(str(json_conf.read()))
except ValueError as e:
raise YunohostError('ssowat_persistent_conf_read_error', error=e.strerror)
except IOError:
ssowat_conf = {} ssowat_conf = {}
else:
ssowat_conf = read_json('/etc/ssowat/conf.json.persistent')
if 'redirected_urls' in ssowat_conf and '/' in ssowat_conf['redirected_urls']: if 'redirected_urls' in ssowat_conf and '/' in ssowat_conf['redirected_urls']:
del ssowat_conf['redirected_urls']['/'] del ssowat_conf['redirected_urls']['/']
try:
with open('/etc/ssowat/conf.json.persistent', 'w+') as f: write_to_json('/etc/ssowat/conf.json.persistent', ssowat_conf)
json.dump(ssowat_conf, f, sort_keys=True, indent=4) os.system('chmod 644 /etc/ssowat/conf.json.persistent')
except IOError as e:
raise YunohostError('ssowat_persistent_conf_write_error', error=e.strerror)
try: try:
ldap.add('uid=%s,ou=users' % username, attr_dict) ldap.add('uid=%s,ou=users' % username, attr_dict)
@ -268,6 +265,11 @@ def user_delete(operation_logger, username, purge=False):
# remove the member from the group # remove the member from the group
if username != group and username in infos["members"]: if username != group and username in infos["members"]:
user_group_update(group, remove=username, sync_perm=False) user_group_update(group, remove=username, sync_perm=False)
# Delete primary group if it exists (why wouldnt it exists ? because some
# epic bug happened somewhere else and only a partial removal was
# performed...)
if username in user_group_list()['groups'].keys():
user_group_delete(username, force=True, sync_perm=True) user_group_delete(username, force=True, sync_perm=True)
ldap = _get_ldap_interface() ldap = _get_ldap_interface()
@ -635,7 +637,7 @@ def user_group_delete(operation_logger, groupname, force=False, sync_perm=True):
# #
# We also can't delete "all_users" because that's a special group... # We also can't delete "all_users" because that's a special group...
existing_users = user_list()['users'].keys() existing_users = user_list()['users'].keys()
undeletable_groups = existing_users + ["all_users", "admins"] undeletable_groups = existing_users + ["all_users", "visitors"]
if groupname in undeletable_groups and not force: if groupname in undeletable_groups and not force:
raise YunohostError('group_cannot_be_deleted', group=groupname) raise YunohostError('group_cannot_be_deleted', group=groupname)
@ -670,13 +672,18 @@ def user_group_update(operation_logger, groupname, add=None, remove=None, force=
from yunohost.permission import permission_sync_to_user from yunohost.permission import permission_sync_to_user
from yunohost.utils.ldap import _get_ldap_interface from yunohost.utils.ldap import _get_ldap_interface
existing_users = user_list()['users'].keys()
# Refuse to edit a primary group of a user (e.g. group 'sam' related to user 'sam') # Refuse to edit a primary group of a user (e.g. group 'sam' related to user 'sam')
# Those kind of group should only ever contain the user (e.g. sam) and only this one. # Those kind of group should only ever contain the user (e.g. sam) and only this one.
# We also can't edit "all_users" without the force option because that's a special group... # We also can't edit "all_users" without the force option because that's a special group...
existing_users = user_list()['users'].keys() if not force:
uneditable_groups = existing_users + ["all_users", "admins"] if groupname == "all_users":
if groupname in uneditable_groups and not force: raise YunohostError('group_cannot_edit_all_users')
raise YunohostError('group_cannot_be_edited', group=groupname) elif groupname == "visitors":
raise YunohostError('group_cannot_edit_visitors')
elif groupname in existing_users:
raise YunohostError('group_cannot_edit_primary_group', group=groupname)
# We extract the uid for each member of the group to keep a simple flat list of members # We extract the uid for each member of the group to keep a simple flat list of members
current_group = user_group_info(groupname)["members"] current_group = user_group_info(groupname)["members"]

View file

@ -33,6 +33,8 @@ class YunohostError(MoulinetteError):
""" """
def __init__(self, key, raw_msg=False, *args, **kwargs): def __init__(self, key, raw_msg=False, *args, **kwargs):
self.key = key # Saving the key is useful for unit testing
self.kwargs = kwargs # Saving the key is useful for unit testing
if raw_msg: if raw_msg:
msg = key msg = key
else: else: