diff --git a/README.md b/README.md
index fa7e055..68c36a7 100644
--- a/README.md
+++ b/README.md
@@ -42,15 +42,17 @@ Launch `configure-module`, by setting the following parameters:
- `lets_encrypt`: Set to `true` to enable automatic SSL certificate generation via Let's Encrypt for both domains.
- `ldap_domain`: The LDAP domain name to be used for authentication.
- `mail_from`: The mail sender address for notification mails
+- `nethvoice_auth_url`: The NethVoice authentication URL to enable NethVoice integration, if set the `matrix2acrobits` service will be configured and started.
Example:
- api-cli run module/matrix1/configure-module --data '{"synapse_domain_name": "matrix.example.com", "element_domain_name": "chat.example.com", "cinny_domain_name": "cinny.example.com", "lets_encrypt": true, "ldap_domain": "users.example.com", "mail_from": "noreply@example.com"}'
+ api-cli run module/matrix1/configure-module --data '{"synapse_domain_name": "matrix.example.com", "element_domain_name": "chat.example.com", "cinny_domain_name": "cinny.example.com", "lets_encrypt": true, "ldap_domain": "users.example.com", "mail_from": "noreply@example.com", "nethvoice_auth_url": "https://nethvoice.nethserver.org/freepbx/rest/testextauth"}'
The above command will:
- Start and configure the Synapse Matrix homeserver with LDAP authentication
- Deploy Element Web client and Cinny client configured to connect to the local Synapse instance
- Set up Traefik routes for both domains with automatic SSL certificates
+- Start Matrix2Acrobits Application Service
Access your Matrix installation:
- Matrix server: `https://matrix.example.com`
diff --git a/build-images.sh b/build-images.sh
index 3658430..dd16f57 100755
--- a/build-images.sh
+++ b/build-images.sh
@@ -37,10 +37,10 @@ buildah add "${container}" ui/dist /ui
# Setup the entrypoint, ask to reserve three TCP ports and set a rootless container
buildah config --entrypoint=/ \
--label="org.nethserver.authorizations=traefik@node:routeadm cluster:accountconsumer" \
- --label="org.nethserver.tcp-ports-demand=4" \
+ --label="org.nethserver.tcp-ports-demand=5" \
--label="org.nethserver.rootfull=0" \
--label="org.nethserver.max-per-node=1" \
- --label="org.nethserver.images=docker.io/postgres:14.19-alpine ghcr.io/element-hq/synapse:v1.138.2 ghcr.io/element-hq/element-web:v1.12.0 ghcr.io/cinnyapp/cinny:v4.10.2" \
+ --label="org.nethserver.images=docker.io/postgres:14.19-alpine ghcr.io/element-hq/synapse:v1.138.2 ghcr.io/element-hq/element-web:v1.12.0 ghcr.io/cinnyapp/cinny:v4.10.2 ghcr.io/nethesis/matrix2acrobits:0.0.4" \
"${container}"
# Commit the image
buildah commit "${container}" "${repobase}/${reponame}"
diff --git a/imageroot/actions/configure-module/20configure b/imageroot/actions/configure-module/20configure
index 7a59eb5..0141b3c 100755
--- a/imageroot/actions/configure-module/20configure
+++ b/imageroot/actions/configure-module/20configure
@@ -20,6 +20,7 @@ cinny_domain_name = request.get('cinny_domain_name', '')
lets_encrypt = request.get('lets_encrypt', False)
ldap_domain = request.get('ldap_domain', '')
mail_from = request.get('mail_from', '')
+nethvoice_auth_url = request.get('nethvoice_auth_url', '')
if not synapse_domain_name:
print("ERROR: Synapse_domain_name is required", file=sys.stderr)
@@ -38,6 +39,7 @@ env_vars['CINNY_DOMAIN_NAME'] = cinny_domain_name
env_vars['LDAP_DOMAIN'] = ldap_domain
env_vars['MAIL_FROM'] = mail_from
env_vars['LETS_ENCRYPT'] = '1' if lets_encrypt else '0'
+env_vars['NETHVOICE_AUTH_URL'] = nethvoice_auth_url
# Get allocated TCP ports from environment - NS8 allocates sequential ports
tcp_ports = os.environ.get('TCP_PORTS', '20001').split(',')
@@ -47,6 +49,7 @@ env_vars['SYNAPSE_PORT'] = tcp_ports[0]
env_vars['ELEMENT_WEB_PORT'] = tcp_ports[1]
env_vars['CINNY_PORT'] = tcp_ports[2]
env_vars['POSTGRES_PORT'] = tcp_ports[3]
+env_vars['M2A_PROXY_PORT'] = tcp_ports[4]
# Write updated configuration
agent.write_envfile("config.env", env_vars)
@@ -117,3 +120,67 @@ else:
# Bind the new domain, overriding previous values (unbind)
agent.bind_user_domains([ldap_domain])
+
+
+# Enable or disable matrix2acrobits proxy routes depending on nethvoice_auth_url
+m2a_port = env_vars.get('M2A_PROXY_PORT', '')
+module_id = os.environ.get('MODULE_ID', 'matrix1')
+
+if nethvoice_auth_url:
+ proxy_url = 'http://127.0.0.1:' + (m2a_port if m2a_port else '8080')
+ # create /m2a route
+ response = agent.tasks.run(
+ agent_id=agent.resolve_agent_id('traefik@node'),
+ action='set-route',
+ data={
+ 'instance': module_id + '-m2a',
+ 'name': module_id + '-m2a',
+ 'host': synapse_domain_name,
+ 'path': '/m2a',
+ 'url': proxy_url,
+ 'lets_encrypt': lets_encrypt,
+ 'strip_prefix': True,
+ },
+ )
+ agent.assert_exp(response['exit_code'] == 0)
+
+ # create push notification route
+ response = agent.tasks.run(
+ agent_id=agent.resolve_agent_id('traefik@node'),
+ action='set-route',
+ data={
+ 'instance': module_id + '-push',
+ 'name': module_id + '-push',
+ 'host': synapse_domain_name,
+ 'path': '/_matrix/push/v1/notify',
+ 'url': proxy_url,
+ 'lets_encrypt': lets_encrypt,
+ 'strip_prefix': False,
+ },
+ )
+ agent.assert_exp(response['exit_code'] == 0)
+
+ m2a = {
+ 'MATRIX_HOMESERVER_URL': 'https://' + synapse_domain_name,
+ 'PROXY_PORT': env_vars['M2A_PROXY_PORT'],
+ 'AS_USER_ID': '@_acrobits_proxy:' + synapse_domain_name,
+ 'EXT_AUTH_URL': nethvoice_auth_url,
+ 'LOGLEVEL': 'info',
+ }
+ agent.write_envfile("m2a.env", m2a)
+else:
+ response = agent.tasks.run(
+ agent_id=agent.resolve_agent_id('traefik@node'),
+ action='delete-route',
+ data={
+ 'instance': module_id + '-m2a'
+ },
+ )
+
+ response = agent.tasks.run(
+ agent_id=agent.resolve_agent_id('traefik@node'),
+ action='delete-route',
+ data={
+ 'instance': module_id + '-push'
+ },
+ )
diff --git a/imageroot/actions/configure-module/80start_services b/imageroot/actions/configure-module/80start_services
index acfc6a0..f410641 100755
--- a/imageroot/actions/configure-module/80start_services
+++ b/imageroot/actions/configure-module/80start_services
@@ -51,3 +51,14 @@ if [[ -n ${CINNY_DOMAIN_NAME} ]]; then
else
systemctl --user stop cinny.service
fi
+
+# Manage matrix2acrobits service
+if [[ -n ${NETHVOICE_AUTH_URL} ]]; then
+ # Enable NethVoice Matrix Auth service
+ systemctl --user enable matrix2acrobits.service
+ # Restart NethVoice Matrix Auth service
+ systemctl --user restart matrix2acrobits.service
+else
+ # Disable and stop NethVoice Matrix Auth service
+ systemctl --user disable --now matrix2acrobits.service
+fi
\ No newline at end of file
diff --git a/imageroot/actions/configure-module/validate-input.json b/imageroot/actions/configure-module/validate-input.json
index 1716942..16d74ac 100644
--- a/imageroot/actions/configure-module/validate-input.json
+++ b/imageroot/actions/configure-module/validate-input.json
@@ -10,7 +10,8 @@
"cinny_domain_name": "cinny.example.com",
"lets_encrypt": true,
"ldap_domain": "users.example.com",
- "mail_from": "noreply@example.com"
+ "mail_from": "noreply@example.com",
+ "nethvoice_auth_url": "https://voice.nethserver.org/freepbx/rest/testextauth"
}
],
"type": "object",
@@ -73,5 +74,19 @@
}
]
}
+ ,
+ "nethvoice_auth_url": {
+ "description": "NethVoice Authentication URL",
+ "oneOf": [
+ {
+ "type": "string",
+ "format": "uri"
+ },
+ {
+ "type": "string",
+ "maxLength": 0
+ }
+ ]
+ }
}
}
diff --git a/imageroot/actions/create-module/30grants b/imageroot/actions/create-module/30grants
new file mode 100755
index 0000000..30b31d8
--- /dev/null
+++ b/imageroot/actions/create-module/30grants
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2025 Nethesis S.r.l.
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+set -e # exit immediately if an error occurs
+exec 1>&2 # ensure any output is sent to stderr
+
+#
+# Allow other modules to configure Matrix and read the
+# module configuration
+#
+redis-exec SADD "${AGENT_ID}/roles/matrixadm" "configure-module" "get-*"
+
+#
+# Allow the instance itself to run some subtasks during restore and clone actions
+#
+redis-exec SADD "${AGENT_ID}/roles/selfadm" \
+ "configure-module"
diff --git a/imageroot/actions/get-configuration/20read b/imageroot/actions/get-configuration/20read
index cb87dff..f876ea5 100755
--- a/imageroot/actions/get-configuration/20read
+++ b/imageroot/actions/get-configuration/20read
@@ -35,6 +35,7 @@ if os.path.exists("config.env"):
config['mail_from'] = env_vars.get('MAIL_FROM', '')
config['lets_encrypt'] = env_vars.get('LETS_ENCRYPT', '0') == '1'
config['domains_list'] = domains
+ config['nethvoice_auth_url'] = env_vars.get('NETHVOICE_AUTH_URL', '')
else:
# No configuration file found, return empty configuration
config['synapse_domain_name'] = ''
@@ -44,5 +45,6 @@ else:
config['mail_from'] = ''
config['lets_encrypt'] = False
config['domains_list'] = domains
+ config['nethvoice_auth_url'] = ''
json.dump(config, fp=sys.stdout)
diff --git a/imageroot/actions/get-configuration/validate-output.json b/imageroot/actions/get-configuration/validate-output.json
index ac91efe..1d0ddff 100644
--- a/imageroot/actions/get-configuration/validate-output.json
+++ b/imageroot/actions/get-configuration/validate-output.json
@@ -50,5 +50,19 @@
}
]
}
+ ,
+ "nethvoice_auth_url": {
+ "description": "NethVoice Authentication URL",
+ "oneOf": [
+ {
+ "type": "string",
+ "format": "uri"
+ },
+ {
+ "type": "string",
+ "maxLength": 0
+ }
+ ]
+ }
}
}
diff --git a/imageroot/bin/configure-matrix b/imageroot/bin/configure-matrix
index 1005ed0..bc3606e 100755
--- a/imageroot/bin/configure-matrix
+++ b/imageroot/bin/configure-matrix
@@ -47,8 +47,11 @@ if not os.path.exists(secrets_file):
"REGISTRATION_SECRET": generate_secret(),
"MACAROON_SECRET": generate_secret(),
"FORM_SECRET": generate_secret(),
- "SYNAPSE_SECRET": generate_secret()
+ "SYNAPSE_SECRET": generate_secret(),
+ "M2A_AS_TOKEN": generate_secret(64),
+ "M2A_HS_TOKEN": generate_secret(64)
}
+ secrets_env["MATRIX_AS_TOKEN"] = secrets_env['M2A_AS_TOKEN']
agent.write_envfile(secrets_file, secrets_env)
# Read generated secrets
@@ -74,6 +77,17 @@ with open(f'{template_dir}/synapse-homeserver.yaml', 'r') as f:
with open('synapse-config/homeserver.yaml', 'w') as f:
f.write(synapse_config)
+ # If NETHVOICE_AUTH_URL is set, append the appservice lines to the generated homeserver.yaml
+ if env_vars.get('NETHVOICE_AUTH_URL'):
+ f.write('\napp_service_config_files:\n - /data/config/matrix2acrobits.yaml\n')
+
+# Expand matrix2acrobits.yaml into the synapse config directory
+with open(f'{template_dir}/matrix2acrobits.yaml', 'r') as f:
+ matrix_a2a = substitute_env_vars(f.read(), env_vars)
+
+with open('synapse-config/matrix2acrobits.yaml', 'w') as f:
+ f.write(matrix_a2a)
+
# Copy log config
with open(f'{template_dir}/synapse-log.config', 'r') as f:
log_config = f.read()
diff --git a/imageroot/etc/state-include.conf b/imageroot/etc/state-include.conf
index 50e3541..6cbc378 100644
--- a/imageroot/etc/state-include.conf
+++ b/imageroot/etc/state-include.conf
@@ -3,3 +3,4 @@ state/database.env
state/config.json
volumes/synapse-data
+volumes/matrix2acrobits-data
diff --git a/imageroot/systemd/user/matrix2acrobits.service b/imageroot/systemd/user/matrix2acrobits.service
new file mode 100644
index 0000000..c42b8a7
--- /dev/null
+++ b/imageroot/systemd/user/matrix2acrobits.service
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2025 Nethesis S.r.l.
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+#
+# This systemd unit starts matrix2acrobits client using Podman.
+#
+[Unit]
+Description=matrix2acrobits Matrix Client
+After=network-online.target synapse.service
+Wants=synapse.service
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+EnvironmentFile=%S/state/environment
+EnvironmentFile=%S/state/config.env
+WorkingDirectory=%S/state
+Restart=always
+ExecStartPre=/bin/rm -f %t/matrix2acrobits.pid %t/matrix2acrobits.ctr-id
+ExecStartPre=-runagent configure-matrix
+ExecStart=/usr/bin/podman run \
+ --detach \
+ --conmon-pidfile=%t/matrix2acrobits.pid \
+ --cidfile=%t/matrix2acrobits.ctr-id \
+ --cgroups=no-conmon \
+ --replace --name=matrix2acrobits \
+ --network=host \
+ --env-file=%S/state/matrix-secrets.env \
+ --env-file=%S/state/m2a.env \
+ --volume=matrix2acrobits-data:/tmp \
+ ${MATRIX2ACROBITS_IMAGE}
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/matrix2acrobits.ctr-id -t 10
+ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/matrix2acrobits.ctr-id
+PIDFile=%t/matrix2acrobits.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
diff --git a/imageroot/templates/matrix2acrobits.yaml b/imageroot/templates/matrix2acrobits.yaml
new file mode 100644
index 0000000..d094133
--- /dev/null
+++ b/imageroot/templates/matrix2acrobits.yaml
@@ -0,0 +1,15 @@
+id: acrobits-proxy
+url: http://127.0.0.1:${M2A_PROXY_PORT}
+as_token: "${M2A_AS_TOKEN}"
+hs_token: "${M2A_HS_TOKEN}"
+sender_localpart: _acrobits_proxy
+namespaces:
+ users:
+ - exclusive: false
+ regex: '@.*'
+ aliases:
+ - exclusive: false
+ regex: '.*'
+ rooms:
+ - exclusive: false
+ regex: '.*'
\ No newline at end of file
diff --git a/ui/public/i18n/ar/translation.json b/ui/public/i18n/ar/translation.json
deleted file mode 100644
index 753d1f1..0000000
--- a/ui/public/i18n/ar/translation.json
+++ /dev/null
@@ -1,57 +0,0 @@
-{
- "error": {
- "403": "العملية غير مصرح بها",
- "401": "مصادقة غير صالحة",
- "generic_error": "حدث خطأ",
- "error": "خطأ",
- "network_timeout": "انتهت مهلة الخادم",
- "404": "لم يتم العثور على المصدر",
- "network_error": "خطا في الاتصال",
- "validation_error": "خطئ في التحقق",
- "cannot_retrieve_module_info": "لا يمكن استرداد معلومات الـ module",
- "cannot_retrieve_installed_modules": "لا يمكن استرداد الـ moduls المثبتة"
- },
- "common": {
- "required": "مطلوب",
- "work_in_progress": "جاري المعالجة",
- "processing": "جاري المعالجة"
- },
- "about": {
- "title": "معلومات"
- },
- "action": {
- "list-backup-repositories": "قائمة مستودعات النسخ الاحتياطي",
- "list-backups": "قائمة النسخ الاحتياطية",
- "get-status": "معلومات الحالة",
- "get-configuration": "احصل على التهيئة",
- "configure-module": "تهيئة الـmodule",
- "get-module-info": "احصل على معلومات الـ module",
- "get-name": "احصل على إسم",
- "list-installed-modules": "قائمة الـ modules المثبتة"
- },
- "task": {
- "cannot_create_task": "لا يمكن إنشاء المهمة {action}"
- },
- "settings": {
- "title": "إعدادات",
- "save": "حفظ",
- "configure_instance": "تهيئة {instance}",
- "test_field": "حقل اختبار"
- },
- "status": {
- "title": "الحالة",
- "app_instance": "تطبيق instance",
- "services": "الخدمة | الخدمات",
- "app_images": "صورة التطبيق | صور التطبيق",
- "app_volumes": "حجم التطبيق | احجام التطبيق",
- "mount": "تحميل (تلقيم)",
- "no_services": "لا خدمات",
- "installation_node": "تثبيت Node",
- "node": "Node",
- "name": "الاسم",
- "size": "الحجم",
- "created": "تم الانشاء",
- "no_images": "لا يوجد صور",
- "no_volumes": "لايوجد احجام"
- }
-}
diff --git a/ui/public/i18n/de/translation.json b/ui/public/i18n/de/translation.json
deleted file mode 100644
index a5b8265..0000000
--- a/ui/public/i18n/de/translation.json
+++ /dev/null
@@ -1,57 +0,0 @@
-{
- "error": {
- "403": "Vorgang nicht autorisiert",
- "cannot_retrieve_installed_modules": "Fehler beim Abruf installierter Module",
- "401": "Authentifizierung fehlerhaft",
- "cannot_retrieve_module_info": "Fehler beim Abruf der Modul-Info",
- "generic_error": "Etwas ist schief gegangen",
- "error": "Fehler",
- "network_timeout": "Netzwerk-Zeitüberschreitung",
- "404": "Ressource nicht gefunden",
- "network_error": "Netzwerk-Fehler",
- "validation_error": "Fehler bei der Validierung"
- },
- "settings": {
- "test_field": "Testfeld",
- "configure_instance": "{instance} konfigurieren",
- "save": "Speichern",
- "title": "Einstellungen"
- },
- "common": {
- "required": "Erforderlich",
- "work_in_progress": "In Bearbeitung",
- "processing": "Verarbeitung läuft..."
- },
- "status": {
- "created": "Erstellt",
- "size": "Größe",
- "name": "Name",
- "no_images": "Keine Abbilder",
- "app_volumes": "App Volumen | App Volumen",
- "services": "Dienst | Dienste",
- "app_images": "App Abbild | App Abbilder",
- "no_services": "Keine Dienste",
- "app_instance": "App Instanz",
- "mount": "Mount",
- "title": "Status",
- "installation_node": "Knoten der Installation",
- "node": "Knoten",
- "no_volumes": "Keine Volumen"
- },
- "about": {
- "title": "Über"
- },
- "action": {
- "list-backup-repositories": "Backup-Speicherorte auflisten",
- "get-module-info": "Modul-Info abrufen",
- "list-installed-modules": "Installierte Module auflisten",
- "list-backups": "Backups auflisten",
- "get-status": "Status abrufen",
- "configure-module": "Modul konfigurieren",
- "get-configuration": "Konfiguration abrufen",
- "get-name": "Name abrufen"
- },
- "task": {
- "cannot_create_task": "Aufgabe {action} kann nicht erstellt werden"
- }
-}
diff --git a/ui/public/i18n/en/translation.json b/ui/public/i18n/en/translation.json
index 4280500..3839673 100644
--- a/ui/public/i18n/en/translation.json
+++ b/ui/public/i18n/en/translation.json
@@ -37,7 +37,10 @@
"mail_from_placeholder": "e.g. noreply@example.com",
"mail_from_format": "Must be a valid mail address",
"enabled": "Enabled",
- "disabled": "Disabled"
+ "disabled": "Disabled",
+ "nethvoice_auth_url": "NethVoice authentication URL",
+ "nethvoice_auth_url_placeholder": "e.g. https://voice.nethserver.org/freepbx/rest/testextauth",
+ "nethvoice_auth_url_placeholder_tooltip": "The URL used to authenticate users against NethVoice. It should point to the FreePBX External Auth endpoint. If not set, NethVoice mobile app chat integration will be disabled."
},
"about": {
"title": "About"
diff --git a/ui/public/i18n/es/translation.json b/ui/public/i18n/es/translation.json
deleted file mode 100644
index da1961e..0000000
--- a/ui/public/i18n/es/translation.json
+++ /dev/null
@@ -1,57 +0,0 @@
-{
- "error": {
- "403": "Operación no autorizada",
- "cannot_retrieve_installed_modules": "No se pueden recuperar los módulos instalados",
- "401": "Autentificación inválida",
- "cannot_retrieve_module_info": "No se puede recuperar la información del módulo",
- "generic_error": "Algo ha salido mal",
- "error": "Error",
- "network_timeout": "Tiempo de espera de la red agotado",
- "404": "Recurso no encontrado",
- "network_error": "Error en la red",
- "validation_error": "Error en la validación"
- },
- "settings": {
- "test_field": "Campo de prueba",
- "configure_instance": "Configurar {instance}",
- "save": "Guardar",
- "title": "Ajustes"
- },
- "common": {
- "required": "Obligatorio",
- "work_in_progress": "Trabajando",
- "processing": "Procesando..."
- },
- "status": {
- "created": "Creado",
- "size": "Tamaño",
- "name": "Nombre",
- "no_images": "Sin imágenes",
- "app_volumes": "Volumen de la aplicación| Volumen de las aplicaciones",
- "services": "Servicio | Servicios",
- "app_images": "Imagen de la aplicación| Imágenes de las aplicaciones",
- "no_services": "Sin servicios",
- "app_instance": "Instancia de la aplicación",
- "mount": "Montar",
- "title": "Estado",
- "installation_node": "Nodo de la instalación",
- "node": "Nodo",
- "no_volumes": "Sin volumenes"
- },
- "about": {
- "title": "Acerca de"
- },
- "action": {
- "list-backup-repositories": "Mostrar repositorios de respaldo",
- "get-module-info": "Obtener información del módulo",
- "list-installed-modules": "Lista de módulos instalados",
- "list-backups": "Mostrar copias de seguridad",
- "get-status": "Obtener el estado",
- "configure-module": "Configurar el módulo",
- "get-configuration": "Obtener los ajustes",
- "get-name": "Obtener el nombre"
- },
- "task": {
- "cannot_create_task": "No se puede crear la tarea {action}"
- }
-}
diff --git a/ui/public/i18n/eu/translation.json b/ui/public/i18n/eu/translation.json
deleted file mode 100644
index 38649d9..0000000
--- a/ui/public/i18n/eu/translation.json
+++ /dev/null
@@ -1,57 +0,0 @@
-{
- "error": {
- "403": "Operation not authorized",
- "cannot_retrieve_installed_modules": "Cannot retrieve installed modules",
- "401": "Invalid authentication",
- "cannot_retrieve_module_info": "Cannot retrieve module info",
- "generic_error": "Something went wrong",
- "error": "Error",
- "network_timeout": "Network timeout",
- "404": "Resource not found",
- "network_error": "Network error",
- "validation_error": "Validation error"
- },
- "settings": {
- "test_field": "Proba-eremua",
- "configure_instance": "Configure {instance}",
- "save": "Save",
- "title": "Settings"
- },
- "common": {
- "required": "Beharrezkoa",
- "work_in_progress": "Work in progress",
- "processing": "Processing..."
- },
- "status": {
- "created": "Created",
- "size": "Size",
- "name": "Name",
- "no_images": "No images",
- "app_volumes": "App volume | App volumes",
- "services": "Service | Services",
- "app_images": "App image | App images",
- "no_services": "No services",
- "app_instance": "App instance",
- "mount": "Mount",
- "title": "Status",
- "installation_node": "Installation node",
- "node": "Node",
- "no_volumes": "No volumes"
- },
- "about": {
- "title": "Honi buruz"
- },
- "action": {
- "list-backup-repositories": "List backup repositories",
- "get-module-info": "Get module info",
- "list-installed-modules": "List installed modules",
- "list-backups": "List backups",
- "get-status": "Get status",
- "configure-module": "Configure module",
- "get-configuration": "Get configuration",
- "get-name": "Get name"
- },
- "task": {
- "cannot_create_task": "Cannot create task {action}"
- }
-}
diff --git a/ui/public/i18n/it/translation.json b/ui/public/i18n/it/translation.json
index 5e1952c..4fb8303 100644
--- a/ui/public/i18n/it/translation.json
+++ b/ui/public/i18n/it/translation.json
@@ -1,47 +1,63 @@
{
"common": {
"required": "Obbligatorio",
- "processing": "In elaborazione…",
- "work_in_progress": "In lavorazione"
+ "work_in_progress": "In lavorazione",
+ "processing": "In elaborazione…"
},
"status": {
- "node": "Nodo",
- "services": "Servizio | Servizi",
- "no_volumes": "Nessun volume",
"title": "Stato",
+ "app_instance": "Istanza app",
+ "services": "Servizio | Servizi",
+ "app_images": "Immagine app | Immagini app",
+ "app_volumes": "Volume app | Volumi app",
+ "installation_node": "Nodo di installazione",
+ "node": "Nodo",
"name": "Nome",
"size": "Dimensione",
"created": "Creato",
+ "mount": "Percorso di mount",
"no_services": "Nessun servizio",
"no_images": "Nessuna immagine",
- "app_images": "Immagine app|Immagini app",
- "app_instance": "Istanza app",
- "app_volumes": "Volume app|Volumi app",
- "installation_node": "Nodo di installazione",
- "mount": "Percorso di mount"
+ "no_volumes": "Nessun volume"
},
"settings": {
- "save": "Salva",
"title": "Impostazioni",
"configure_instance": "Configura {instance}",
- "test_field": "Campo di test"
+ "save": "Salva",
+ "synapse_domain_name": "Dominio server Matrix",
+ "synapse_domain_placeholder": "es. matrix.example.com",
+ "element_domain_name": "Dominio client Element",
+ "element_domain_placeholder": "es. chat.example.com",
+ "cinny_domain_name": "Dominio client Cinny",
+ "cinny_domain_placeholder": "es. cinny.example.com",
+ "ldap_domain": "Dominio LDAP",
+ "choose_ldap_domain": "Scegli il dominio LDAP",
+ "choose_the_ldap_domain_to_use": "Scegli il dominio LDAP da usare",
+ "mail_from": "Indirizzo mittente notifiche",
+ "mail_from_placeholder": "es. noreply@example.com",
+ "mail_from_format": "Deve essere un indirizzo email valido",
+ "enabled": "Abilitato",
+ "disabled": "Disabilitato",
+ "nethvoice_auth_url": "URL autenticazione NethVoice",
+ "nethvoice_auth_url_placeholder": "es. https://voice.nethserver.org/freepbx/rest/testextauth",
+ "nethvoice_auth_url_placeholder_tooltip": "L'URL usato per autenticare gli utenti contro NethVoice. Dovrebbe puntare all'endpoint FreePBX External Auth. Se non impostato, l'integrazione chat dell'app mobile NethVoice sarà disabilitata."
},
"error": {
"error": "Errore",
- "404": "Risorsa non trovata",
+ "generic_error": "Qualcosa è andato storto",
"validation_error": "Errore di validazione",
"network_error": "Errore di rete",
- "cannot_retrieve_installed_modules": "Impossibile elencare moduli installati",
- "cannot_retrieve_module_info": "Impossibile recuperare info modulo",
"network_timeout": "Timeout di rete",
- "generic_error": "Qualcosa è andato storto",
"401": "Autenticazione non valida",
- "403": "Operazione non autorizzata"
+ "403": "Operazione non autorizzata",
+ "404": "Risorsa non trovata",
+ "cannot_retrieve_module_info": "Impossibile recuperare info modulo",
+ "cannot_retrieve_installed_modules": "Impossibile elencare moduli installati"
},
"action": {
- "configure-module": "Configura modulo",
- "get-configuration": "Visualizza configurazione",
"get-status": "Visualizza stato",
+ "get-configuration": "Visualizza configurazione",
+ "configure-module": "Configura modulo",
"get-module-info": "Visualizza info modulo",
"get-name": "Visualizza nome",
"list-backup-repositories": "Elenca repository di backup",
diff --git a/ui/public/i18n/pt/translation.json b/ui/public/i18n/pt/translation.json
deleted file mode 100644
index 4ca6726..0000000
--- a/ui/public/i18n/pt/translation.json
+++ /dev/null
@@ -1,57 +0,0 @@
-{
- "error": {
- "403": "Operation not authorized",
- "cannot_retrieve_installed_modules": "Cannot retrieve installed modules",
- "401": "Invalid authentication",
- "cannot_retrieve_module_info": "Cannot retrieve module info",
- "generic_error": "Something went wrong",
- "error": "Error",
- "network_timeout": "Network timeout",
- "404": "Resource not found",
- "network_error": "Network error",
- "validation_error": "Validation error"
- },
- "settings": {
- "test_field": "Campo de teste",
- "configure_instance": "Configure {instance}",
- "save": "Save",
- "title": "Settings"
- },
- "common": {
- "required": "Required",
- "work_in_progress": "Work in progress",
- "processing": "Processing..."
- },
- "status": {
- "created": "Created",
- "size": "Size",
- "name": "Name",
- "no_images": "No images",
- "app_volumes": "App volume | App volumes",
- "services": "Service | Services",
- "app_images": "App image | App images",
- "no_services": "No services",
- "app_instance": "App instance",
- "mount": "Mount",
- "title": "Status",
- "installation_node": "Installation node",
- "node": "Node",
- "no_volumes": "No volumes"
- },
- "about": {
- "title": "About"
- },
- "action": {
- "list-backup-repositories": "List backup repositories",
- "get-module-info": "Get module info",
- "list-installed-modules": "List installed modules",
- "list-backups": "List backups",
- "get-status": "Get status",
- "configure-module": "Configure module",
- "get-configuration": "Get configuration",
- "get-name": "Get name"
- },
- "task": {
- "cannot_create_task": "Cannot create task {action}"
- }
-}
diff --git a/ui/public/i18n/pt_BR/translation.json b/ui/public/i18n/pt_BR/translation.json
deleted file mode 100644
index bcdcb52..0000000
--- a/ui/public/i18n/pt_BR/translation.json
+++ /dev/null
@@ -1,57 +0,0 @@
-{
- "common": {
- "required": "Required",
- "work_in_progress": "Work in progress",
- "processing": "Processing..."
- },
- "status": {
- "services": "Service | Services",
- "app_instance": "App instance",
- "title": "Status",
- "created": "Created",
- "size": "Size",
- "name": "Name",
- "no_images": "No images",
- "app_volumes": "App volume | App volumes",
- "app_images": "App image | App images",
- "no_services": "No services",
- "mount": "Mount",
- "installation_node": "Installation node",
- "node": "Node",
- "no_volumes": "No volumes"
- },
- "error": {
- "403": "Operation not authorized",
- "401": "Invalid authentication",
- "generic_error": "Something went wrong",
- "error": "Error",
- "network_timeout": "Network timeout",
- "404": "Resource not found",
- "network_error": "Network error",
- "validation_error": "Validation error",
- "cannot_retrieve_installed_modules": "Cannot retrieve installed modules",
- "cannot_retrieve_module_info": "Cannot retrieve module info"
- },
- "about": {
- "title": "About"
- },
- "action": {
- "list-backup-repositories": "List backup repositories",
- "list-backups": "List backups",
- "get-module-info": "Get module info",
- "list-installed-modules": "List installed modules",
- "get-status": "Get status",
- "configure-module": "Configure module",
- "get-configuration": "Get configuration",
- "get-name": "Get name"
- },
- "task": {
- "cannot_create_task": "Cannot create task {action}"
- },
- "settings": {
- "title": "Settings",
- "configure_instance": "Configure {instance}",
- "save": "Save",
- "test_field": "Test field"
- }
-}
diff --git a/ui/public/i18n/ta/translation.json b/ui/public/i18n/ta/translation.json
deleted file mode 100644
index 107113d..0000000
--- a/ui/public/i18n/ta/translation.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "error": {
- "network_timeout": "பிணையம் நேரம் முடிந்தது",
- "403": "செயல்பாடு அங்கீகரிக்கப்படவில்லை",
- "cannot_retrieve_installed_modules": "நிறுவப்பட்ட தொகுதிகளை மீட்டெடுக்க முடியாது",
- "401": "தவறான ஏற்பு",
- "cannot_retrieve_module_info": "தொகுதி தகவலை மீட்டெடுக்க முடியாது",
- "generic_error": "ஏதோ தவறு நடந்தது",
- "error": "பிழை",
- "404": "சான்று கிடைக்கவில்லை",
- "network_error": "பிணைய பிழை",
- "validation_error": "சரிபார்ப்பு பிழை"
- },
- "common": {
- "required": "தேவை",
- "work_in_progress": "வேலை முன்னேற்றத்தில் உள்ளது"
- },
- "status": {
- "created": "உருவாக்கப்பட்டது",
- "size": "அளவு",
- "name": "பெயர்",
- "no_images": "படங்கள் இல்லை",
- "app_volumes": "பயன்பாட்டு தொகுதி | பயன்பாட்டு தொகுதிகள்",
- "services": "பணி | சேவைகள்",
- "app_images": "பயன்பாட்டு படம் | பயன்பாட்டு படங்கள்",
- "no_services": "சேவைகள் இல்லை",
- "app_instance": "பயன்பாட்டு நிகழ்வு",
- "mount": "மவுண்ட்",
- "title": "நிலை",
- "installation_node": "நிறுவல் முனை",
- "node": "கணு",
- "no_volumes": "தொகுதிகள் இல்லை"
- },
- "about": {
- "title": "பற்றி"
- },
- "action": {
- "get-module-info": "தொகுதி தகவலைப் பெறுங்கள்",
- "get-status": "அந்தச்தைப் பெறுங்கள்",
- "configure-module": "தொகுதியை உள்ளமைக்கவும்",
- "get-configuration": "உள்ளமைவைப் பெறுங்கள்",
- "get-name": "பெயரைப் பெறுங்கள்"
- },
- "task": {
- "cannot_create_task": "பணியை உருவாக்க முடியாது {action}"
- },
- "settings": {
- "save": "சேமி",
- "title": "அமைப்புகள்"
- }
-}
diff --git a/ui/public/i18n/uk/translation.json b/ui/public/i18n/uk/translation.json
deleted file mode 100644
index 3b7f2f2..0000000
--- a/ui/public/i18n/uk/translation.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "settings": {
- "test_field": "Тестове поле"
- }
-}
diff --git a/ui/src/views/Settings.vue b/ui/src/views/Settings.vue
index 7849548..d3c115f 100644
--- a/ui/src/views/Settings.vue
+++ b/ui/src/views/Settings.vue
@@ -74,6 +74,18 @@
:invalid-message="error.mail_from"
ref="mail_from"
>
+
+
+ {{ $t("settings.nethvoice_auth_url_placeholder_tooltip") }}
+
+