diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3f1236..f4b9244 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -73,4 +73,7 @@
- Fixed typo on docker compose in home and in readme
- Fix on custom theme
- Feature Requested: Allow unsecure HTTP url in redirection
-
\ No newline at end of file
+- 0.7.3
+ - Added Spanish and Galician languages by [cabaseira](https://github.com/cabaseira)
+ - Minor fix to unsecure HTTP Edit to fix [Issue #26](https://github.com/urania-dev/snapp/issues/26)
+ - Removed some dev console.logs.
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index d0501bc..ed5a62c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -13,7 +13,7 @@ RUN npm i
COPY . /app
# Build the SvelteKit app
-ENV SNAPP_VERSION=0.7.2
+ENV SNAPP_VERSION=0.7.3
ENV AUTH_SECRET=lFNiU7T98/44Qlqb4hMUkVcLOpijEI7z722Kxhv4O2Y=
ENV ALLOW_UNSECURE_HTTP=false
diff --git a/src/hooks.server.ts b/src/hooks.server.ts
index 1fdd481..3ffeab9 100644
--- a/src/hooks.server.ts
+++ b/src/hooks.server.ts
@@ -16,7 +16,7 @@ const snappHandler = (async ({ event, resolve }) => {
let theme = event.cookies.get('snapp:theme')?.toString();
let lang = event.cookies.get('snapp:lang')?.toString();
if (!theme || !lang) {
- const user = session
+ const user = session !== null
? await db.users.fetch(session?.user.id).then((user) => user as DBUser)
: null;
diff --git a/src/lib/db/snapps/edit.ts b/src/lib/db/snapps/edit.ts
index 83f35b0..16f57b7 100644
--- a/src/lib/db/snapps/edit.ts
+++ b/src/lib/db/snapps/edit.ts
@@ -22,12 +22,14 @@ export default async function edit(
if (!user) return new SnappError(404, { message: 'auth:not:authorized' });
const regex = new RegExp(/^https:\/\/[^\s/$.?#].[^\s]*$/);
-
+ const allow_unsecure_http =
+ (await this.getSetting('settings:app:allow:unsecure:http'))?.toString().toLocaleLowerCase() ===
+ 'true';
if (!original_url || typeof original_url !== 'string' || original_url.trim() === '')
return new SnappError(400, { message: 'snapps:original:url:unset' });
if (original_url) {
- if (regex.test(original_url) === false)
+ if (allow_unsecure_http === false && regex.test(original_url) === false)
return new SnappError(400, { message: 'snapps:original:url:invalid' });
snapp.original_url = original_url;
}
diff --git a/src/lib/db/users/update.ts b/src/lib/db/users/update.ts
index a8d986f..5f59fe8 100644
--- a/src/lib/db/users/update.ts
+++ b/src/lib/db/users/update.ts
@@ -66,7 +66,6 @@ export default async function updateProfile(
if (roles && roles.length > 0) {
const newRoles = new Set([...roles]);
- console.log(Array.from(newRoles), updatedProfile.roles)
if (
Array.from(newRoles) !== updatedProfile.roles &&
updatedProfile.roles.includes('superadmin') &&
diff --git a/src/routes/(frontend)/dashboard/shorten/+page.server.ts b/src/routes/(frontend)/dashboard/shorten/+page.server.ts
index 3a21345..c40c70d 100644
--- a/src/routes/(frontend)/dashboard/shorten/+page.server.ts
+++ b/src/routes/(frontend)/dashboard/shorten/+page.server.ts
@@ -15,7 +15,6 @@ export async function load({ locals, parent }) {
const ALLOW_UNSECURE_HTTP =
(await db.getSetting('settings:app:allow:unsecure:http'))?.toString()?.toLowerCase() === 'true';
- console.log(ALLOW_UNSECURE_HTTP)
return {
max_urls: user.settings?.max?.urls ?? data.max_urls ?? 0,
existing: await db.snapps.search().where('user_id').equal(session.user.id).returnCount(),
diff --git a/src/routes/(frontend)/dashboard/urls/import/+page.svelte b/src/routes/(frontend)/dashboard/urls/import/+page.svelte
index 3a25df4..8a868d6 100644
--- a/src/routes/(frontend)/dashboard/urls/import/+page.svelte
+++ b/src/routes/(frontend)/dashboard/urls/import/+page.svelte
@@ -55,7 +55,6 @@
});
rows.data.map((snapp) => {
- console.log({ snapp });
const _snapp = {
id: snapp.id,
created: new Date(snapp.created_at),
diff --git a/src/routes/(frontend)/dashboard/users/[username]/+page.svelte b/src/routes/(frontend)/dashboard/users/[username]/+page.svelte
index bb34f03..64cee81 100644
--- a/src/routes/(frontend)/dashboard/users/[username]/+page.svelte
+++ b/src/routes/(frontend)/dashboard/users/[username]/+page.svelte
@@ -353,7 +353,6 @@
}
});
- console.log(form?.message);
await invalidateAll();
};
};
diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts
index 0866554..1e8ddfe 100644
--- a/src/routes/+layout.server.ts
+++ b/src/routes/+layout.server.ts
@@ -2,12 +2,12 @@ import { env } from '$env/dynamic/private';
import { db } from '$lib/db/index.js';
import jsonify from '$lib/utils/jsonify/index.js';
-export async function load({ locals, depends, fetch, cookies }) {
+export async function load({ locals, depends, fetch }) {
depends('snapp:main');
const session = await locals.getSession();
const user =
- session && (await db.users.search().where('id').equal(session?.user.id).returnFirst());
+ session !== null && (await db.users.search().where('id').equal(session?.user.id).returnFirst()) || null;
const theme = locals.theme;
const lang = locals.lang;
diff --git a/src/routes/api/smtp/send/+server.ts b/src/routes/api/smtp/send/+server.ts
index 7a9132e..a88541f 100644
--- a/src/routes/api/smtp/send/+server.ts
+++ b/src/routes/api/smtp/send/+server.ts
@@ -70,7 +70,6 @@ export async function POST({ request, url }) {
.replace('{OUT_TEXT}', OUT_TEXT)
});
- // console.log('Email has been sent', { flag });
return json({
message: 'settings:app:smtp:working',
diff --git a/translations/es.json b/translations/es.json
new file mode 100644
index 0000000..b8c56b4
--- /dev/null
+++ b/translations/es.json
@@ -0,0 +1,438 @@
+{
+ "api:error:too:many:request": "Demasiadas Solicitudes",
+ "api:error:too:many:shorturl": "El número de Snapps excede lo permitido por la plataforma.",
+ "api:invalid:offset": "El desplazamiento del cursor no puede ser mayor que los elementos de la base de datos.",
+ "api:snapp:id:unset": "La ID de Snapp no está configurada.",
+ "api:user:id:unset": "ID de usuario no establecido",
+ "api:user:ids:unset": "ID(s) de usuario no establecido(s)",
+
+ "apikey:copied:clipboard": "Clave API copiada al portapapeles",
+ "apikey:created": "Clave API Creada",
+ "apikey:description": "Para utilizar los puntos finales de API, autorice su llamada con un encabezado de autorización que contenga el token generado. Las claves API son únicas y se relacionan con la cuenta de usuario, compartiendo roles de base de datos.",
+ "apikey:generate": "Generar un token",
+ "apikey:label": "Clave API",
+ "apikey:missing": "Falta la clave API",
+ "apikey:placeholder": "Su CLAVE API se mostrará aquí.",
+ "apikey:redirect:documentation": "Consulte los API Docs completos para aprender cómo usarlos e implementarlos en su flujo de trabajo.",
+ "apikey:revoke": "Revocar token",
+ "apikey:revoke:message": "¿Está seguro? Esto inutilizará la clave actual y bloqueará su acceso a los puntos finales de API.",
+ "apikey:token": "Token",
+ "apikey:token:generated": "El Token ha sido generado",
+ "apikey:token:revoked": "El Token ha sido revocado.",
+
+ "auth:email": "Correo-e",
+ "auth:email:exists": "Este correo electrónico ya está vinculado a una cuenta, intenta restablecer tu contraseña.",
+ "auth:email:invalid": "Por favor ingrese su dirección de correo electrónico válida.",
+ "auth:email:mixed": "Por favor ingrese un correo electrónico o nombre de usuario válido.",
+ "auth:email:placeholder": "Escriba un correo electrónico válido aquí...",
+ "auth:email:unset": "Correo electrónico no proporcionado.",
+ "auth:helping:text": "Autenticación",
+ "auth:in:blacklist": "No está permitido registrarse en esta plataforma. Si cree que se trata de un error, intente ponerse en contacto con el Administrador de la Aplicación.",
+ "auth:not:authenticated": "Los usuarios anónimos no pueden acceder a este recurso.",
+ "auth:not:authorized": "No está autorizado a acceder a este recurso.",
+ "auth:not:in:whitelist": "No está permitido registrarse en esta plataforma. Si cree que se trata de un error, intente ponerse en contacto con el Administrador de la Aplicación.",
+ "auth:password": "Contraseña",
+ "auth:password:change": "Edite y guarde para cambiar su contraseña.",
+ "auth:password:confirm": "Confirmar la Contraseña",
+ "auth:password:confirm:placeholder": "Vuelva a ingresar su contraseña aquí...",
+ "auth:password:forgotten": "¿Olvidaste tu contraseña?",
+ "auth:password:guidelines": "La contraseña debe tener al menos seis caracteres, incluida una letra, un número y un carácter especial.",
+ "auth:password:placeholder": "Escriba su contraseña aquí...",
+ "auth:password:unmatch": "Las contraseñas no coinciden.",
+ "auth:password:unset": "Contraseña no proporcionada.",
+ "auth:profile:delete": "Perfil eliminado exitosamente.",
+ "auth:profile:saved": "Perfil actualizado con éxito.",
+ "auth:recover:password": "Recuperar contraseña",
+ "auth:recover:send": "Enviar restablecimiento de contraseña",
+ "auth:recover:mail:sent": "Se ha enviado un correo a la dirección de correo electrónico de la cuenta. Continúe desde allí.",
+ "auth:redirect:sign:in": "Si ya tiene una cuenta, puede iniciar sesión aquí.",
+ "auth:redirect:sign:up": "Si no tienes una cuenta, puedes registrarte aquí.",
+ "auth:sign:out": "Cerrar Sesión",
+ "auth:sign:in": "Iniciar Sesión",
+ "auth:sign:in:welcome": "Ingrese a su cuenta.",
+ "auth:sign:login": "Iniciar sesión",
+ "auth:sign:signup": "Registrarse",
+ "auth:sign:up": "Registrarse",
+ "auth:sign:up:disabled": "Los registros están actualmente deshabilitados. Si cree que se trata de un error, intente ponerse en contacto con el Administrador de aplicaciones.",
+ "auth:sign:up:welcome": "Crea una cuenta nueva.",
+ "auth:user:not:found": "Usuario no encontrado.",
+ "auth:username": "Nombre de usuario",
+ "auth:username:placeholder": "Escribe aquí tu nombre de usuario...",
+ "auth:username:taken": "El nombre de usuario ya está en uso. Por favor elije otro.",
+ "auth:username:unset": "Nombre de usuario no proporcionado.",
+ "auth:wrong:credentials": "Credenciales incorrectas.",
+ "auth:token:expired": "El token expiró, intenta solicitar uno nuevo.",
+
+ "error:page:title": "Error {{status}}",
+ "error:page:unknown": "Error no reconocido",
+
+ "emails:invited:resend": "Reenviar invitación",
+
+ "emails:invited:object": "Te han invitado a probar {app_name}",
+ "emails:invited:text": "Hola {nombre de usuario}. Este es un correo generado automáticamente que estás recibiendo porque tienes una nueva cuenta creada para ti. Establece una contraseña aquí.",
+ "emails:invited:footer": "¡Visítanos!",
+ "emails:recover:password:object": "Recuperación de cuenta",
+ "emails:recover:password:text": "Hola {nombre de usuario}. Este es un correo generado automáticamente que estás recibiendo para recuperar el acceso a tu cuenta. Cambia la contraseña aquí.
Si no necesitas ninguna acción en tu cuenta, simplemente puedes ignorar este correo electrónico. Si continúas recibiendo correos electrónicos de recuperación de cuenta, comunícate con el Administrador del Sistema.",
+ "emails:recover:password:footer": "¡Visítanos!",
+ "emails:global:out:text": "Este es un correo electrónico generado automáticamente. Por favor no responda a esta dirección. Si necesita ayuda contáctenos en {app_name}",
+
+ "global:appname": "Snapp",
+ "global:misc:cancel": "Cancelar",
+ "global:misc:confirm": "Confirmar",
+ "global:misc:copy": "Copiar",
+ "global:misc:close": "Cerrar",
+ "global:misc:download": "Descargar",
+ "global:misc:loading": "Cargando...",
+ "global:misc:example": "Ejemplo",
+ "global:misc:lang": "Español",
+ "global:misc:month": "Mes",
+ "global:misc:months:apr": "Abril",
+ "global:misc:months:aug": "Agosto",
+ "global:misc:months:dec": "Diciembre",
+ "global:misc:months:feb": "Febrero",
+ "global:misc:months:jan": "Enero",
+ "global:misc:months:jul": "Julio",
+ "global:misc:months:jun": "Junio",
+ "global:misc:months:mar": "Marzo",
+ "global:misc:months:may": "Mayo",
+ "global:misc:months:nov": "Noviembre",
+ "global:misc:months:oct": "Octubre",
+ "global:misc:months:sep": "Septiembre",
+ "global:misc:reset": "Reiniciar",
+ "global:misc:revert": "Descartar",
+ "global:misc:save": "Guardar",
+ "global:misc:search": "Buscar",
+ "global:misc:search:snapps": "Filtrar snaps por cadena",
+ "global:misc:search:users": "Filtrar usuarios por cadena",
+ "global:misc:total": "Total",
+ "global:misc:unset": "sin configurar",
+ "global:misc:year": "Año",
+ "global:pages:admin": "Panel de Administrador",
+ "global:pages:blacklists": "Listas negras",
+ "global:pages:dashboard": "Panel",
+ "global:pages:edit": "Editar: {{id}}",
+ "global:pages:error:page:title": "Error",
+ "global:pages:home": "Inicio",
+ "global:pages:metrics": "Métricas",
+ "global:pages:privacy": "Esta aplicación no almacena sus datos personales ni rastrea ningún comportamiento. Conozca más sobre nuestra Política de Privacidad.",
+ "global:pages:settings": "Ajustes",
+ "global:pages:shorten": "Acortar",
+ "global:pages:snapp": "Snapp: {{id}}",
+ "global:pages:user": "Usuario: {{id}}",
+ "global:pages:user:create": "Crear Usuario",
+ "global:pages:users": "Usuarios",
+ "global:sections:apikey": "Clave REST API",
+ "global:sections:edit": "Editar Snapp",
+ "global:sections:import": "Importar",
+ "global:sections:edit:header": "Editar información de la URL",
+ "global:sections:preferences": "Preferencias",
+ "global:sections:profile": "Perfil de Usuario",
+ "global:sections:settings:app": "Ajustes de Aplicacion",
+ "global:sections:settings:blacklist": "Listas negras",
+ "global:sections:settings:export": "Exportar",
+ "global:sections:settings:limits": "Límites",
+ "global:sections:settings:smtp": "Transportador SMTP",
+ "global:sections:shorten": "Crear un Snapp",
+ "global:sections:shorten:header": "Proporcionar información de URL",
+ "global:sections:snapps": "Snapps",
+ "global:sections:urls": "Lista de URLs",
+ "global:sections:user:create": "Usuarios",
+ "global:sections:user:create:header": "Proporcionar información del usuario",
+ "global:sections:user:edit": "Editar Usuario",
+ "global:sections:users": "Lista de Usuarios",
+ "global:system:error": "Se produjo un error del sistema. Si esto persiste, comuníquese con el administrador del sistema.",
+
+ "graphs:undefined": "--- indefinido ---",
+ "graphs:expired": "--- caducado ---",
+ "graphs:expired:deleted": "Snapps caducados eliminados de las métricas.",
+ "graphs:remove:expired": "Eliminar caducados",
+ "graphs:remove:expired:helper": "Muchas de las métricas se conservan tras la eliminación o la expiración de una URL, perdiendo la afiliación al shortcode para que otros usuarios o usted mismo puedan reutilizarlo. Si prefiere eliminar los datos antiguos para mantener las métricas solo para las instantáneas activas, continúe con esta operación. La acción es irreversible.",
+ "graphs:audience:by": "Público por",
+ "graphs:browser": "Navegador",
+ "graphs:browsers": "Navegadores",
+ "graphs:cities": "Ciudades",
+ "graphs:devices": "Dispositivos",
+ "graphs:countries": "Países",
+ "graphs:ending:date": "Fecha de finalización",
+ "graphs:map": "Mapa",
+ "graphs:map:instructions": "Haga zoom con ctrl + rueda del mouse o clic + arrastra para Mover",
+ "graphs:map:save:position": "Guardar posición actual",
+ "graphs:os": "Sistema Operativo",
+ "graphs:regions": "Regiones",
+ "graphs:snapp:info": "Información del Snapp",
+ "graphs:snapps": "Snapps",
+ "graphs:starting:date": "Fecha de inicio",
+ "graphs:usages:label": "Usos",
+ "graphs:usages:per:day": "Usos por día",
+
+ "settings:api:key:vt": "API VirusTotal",
+ "settings:api:key:vt:description": "El dominio se puede analizar según la solicitud de información de dominio de la API de VirusTotal. Snapp comprobará la reputación del dominio y detendrá cualquier sitio web con puntuación negativa. Una puntuación positiva o nula dará como resultado un dominio válido. Las solicitudes se almacenan en caché en redis durante 24 horas.",
+ "settings:api:key:vt:helper:text": "Regístrate en VirusTotal para obtener una clave API",
+ "settings:api:key:vt:label": "Clave API",
+ "settings:api:key:vt:placeholder": "Introduzca aquí su clave API de VT...",
+ "settings:api:key:vt:protected": "Protegido con la API de Virus Total",
+
+ "settings:app:blacklists:description": "Las listas negras afectarán el registro y la actualización de los detalles del usuario, mientras que prohibir dominios generará un error al acortar una URL.",
+ "settings:app:blacklists:description:error": "Los usuarios baneados recibirán un error del sistema genérico durante el registro.",
+ "settings:app:blacklists:domain:add": "Bloquear dominio",
+ "settings:app:blacklists:domain:added": "El Dominio se ha agregado a la lista negra.",
+ "settings:app:blacklists:domain:description": "Esto afectará el registro de los usuarios y la edición de perfiles, y se comprobarán las listas negras de dominios durante el proceso de acortamiento de URLs.",
+ "settings:app:blacklists:domain:errors:missing": "Falta el Dominio",
+ "settings:app:blacklists:domain:placeholder": "Introduzca el dominio aquí...",
+ "settings:app:blacklists:domain:remove": "Desbloquear",
+ "settings:app:blacklists:domain:remove:message": "El dominio estará disponible nuevamente durante el acortamiento de URLs.",
+ "settings:app:blacklists:domain:removed": "El Dominio se ha eliminado de la lista negra.",
+ "settings:app:blacklists:domains": "Dominios",
+ "settings:app:blacklists:domains:description": "La lista de dominios que generarán un error cuando los usuarios intenten crear una URL corta. Los roles de administrador y superadministrador no se ven afectados por esta configuración.",
+ "settings:app:blacklists:email:add": "Bloquear correo electrónico",
+ "settings:app:blacklists:email:added": "El Correo Electrónico se ha agregado a la lista negra.",
+ "settings:app:blacklists:email:description": "Esto afectará el registro de los usuarios y la edición de perfiles, y se comprobarán las listas negras de dominios durante el proceso de acortamiento de URLs.",
+ "settings:app:blacklists:email:errors:format": "El correo electrónico no es un correo electrónico o proveedor válido (por ejemplo: @ejemplo.es).",
+ "settings:app:blacklists:email:errors:missing": "Falta el Correo Electrónico",
+ "settings:app:blacklists:email:placeholder": "Escriba el correo electrónico aquí...",
+ "settings:app:blacklists:email:remove": "Desbloquear",
+ "settings:app:blacklists:email:remove:message": "El correo electrónico volverá a estar disponible durante la creación del usuario.",
+ "settings:app:blacklists:email:removed": "El Correo Electrónico ha sido eliminado de la lista negra.",
+ "settings:app:blacklists:meta:domains:label": "Dominios bloqueados",
+ "settings:app:blacklists:meta:emails:label": "Correos Electrónicos bloqueados",
+ "settings:app:blacklists:meta:label": "Contadores",
+ "settings:app:blacklists:meta:usernames:label": "Usuarios bloqueados",
+ "settings:app:blacklists:username:add": "Bloquear nombre de usuario",
+ "settings:app:blacklists:username:added": "El Usuario se ha agregado a la lista negra.",
+ "settings:app:blacklists:username:description": "Esto afectará el registro de los usuarios y la edición de perfiles, y se comprobarán las listas negras de dominios durante el proceso de acortamiento de URLs.",
+ "settings:app:blacklists:username:errors:missing": "Falta el nombre de usuario",
+ "settings:app:blacklists:username:placeholder": "Escriba el nombre de usuario aquí...",
+ "settings:app:blacklists:username:remove": "Desbloquear",
+ "settings:app:blacklists:username:remove:message": "El nombre de usuario volverá a estar disponible durante la creación del usuario.",
+ "settings:app:blacklists:username:removed": "El Nombre de Usuario ha sido eliminado de la lista negra.",
+
+ "settings:app:exports:all": "Exportar todo",
+ "settings:app:exports:confirm:message": "Esto exportará todos los snapps de la base de datos y puede requerir algo de tiempo dependiendo del tamaño de la base de datos. ¿Quieres continuar?",
+ "settings:app:exports:helper": "Si desea abandonar Snapp, puede exportar un CSV con todas sus URL abreviadas.",
+ "settings:app:home:description": "En su lugar, redirija a los usuarios a iniciar sesión o al panel de control.",
+ "settings:app:allow:unsecure:http": "Permitir HTTP No Seguro",
+ "settings:app:allow:unsecure:http:description": "Permitir el uso de destinos web HTTP no seguros durante la creación de snapps.",
+ "settings:app:home:label": "Desactivar página de inicio",
+ "settings:app:private:saved": "Preferencias actualizadas",
+ "settings:app:sign:up:description": "Permitir registros externos a esta aplicación.",
+ "settings:app:sign:up:label": "Habilitar registro",
+
+ "settings:app:smtp:active": "Activo",
+ "settings:app:smtp:description": "SMTP se utiliza para el proceso de recuperación de contraseña y envío de primera invitación de acceso a los usuarios generada a través de la plataforma o mediante API REST.",
+ "settings:app:smtp:from:label": "Desde la dirección",
+ "settings:app:smtp:from:placeholder": "norespondas@ejemplo.es",
+ "settings:app:smtp:from:unset": "La dirección de remitente no está configurada",
+ "settings:app:smtp:host:label": "Host",
+ "settings:app:smtp:host:placeholder": "smpt.ejemplo.es",
+ "settings:app:smtp:host:unset": "El host no está configurado.",
+ "settings:app:smtp:not:active": "No activo",
+ "settings:app:smtp:not:working": "El SMTP no funciona como se esperaba, verifique la configuración insertada.",
+ "settings:app:smtp:pass:label": "Contraseña",
+ "settings:app:smtp:pass:placeholder": "contraseña-muy-segura",
+ "settings:app:smtp:pass:unset": "La contraseña no está establecida.",
+ "settings:app:smtp:port:label": "Puerto",
+ "settings:app:smtp:port:placeholder": "465",
+ "settings:app:smtp:port:unset": "El puerto no está configurado.",
+ "settings:app:smtp:user:label": "Usuario",
+ "settings:app:smtp:user:placeholder": "cuenta@ejemplo.es",
+ "settings:app:smtp:user:unset": "El usuario no está configurado.",
+ "settings:app:smtp:working": "El SMTP funciona y acepta correos electrónicos.",
+ "settings:app:switch": "Los interruptores se guardan al cambiar.",
+
+ "settings:app:user:limits:description": "Estas son limitaciones solicitadas por la comunidad para el rol de Usuario. Estos límites no afectarán los roles de administrador y superadministrador. Deshabilitado por defecto.",
+ "settings:app:user:limits:max:placeholder": "0",
+ "settings:app:user:limits:max:rows:label": "Número de filas",
+ "settings:app:user:limits:max:rpd:description": "La cantidad de solicitudes a la API /snapps por día.",
+ "settings:app:user:limits:max:rpd:label": "Solicitudes Máximas por Día",
+ "settings:app:user:limits:max:rpm:description": "La cantidad de solicitudes a la API /snapps por minuto.",
+ "settings:app:user:limits:max:rpm:label": "Solicitudes Máximas por Minuto",
+ "settings:app:user:limits:max:urls:description": "El número máximo de URL cortas que un usuario puede crear.",
+ "settings:app:user:limits:max:urls:label": "Snapp máximos por usuario (predeterminado)",
+ "settings:app:user:limits:max:urls:unset": "El número máximo de URLs no es un número válido.",
+ "settings:app:user:limits:max:usages": "Estas son limitaciones solicitadas por la comunidad para el rol de Usuario. Estos límites no afectarán los roles de administrador y superadministrador. Los límites están deshabilitados de forma predeterminada.",
+ "settings:app:user:limits:max:usages:placeholder": "Usos máximos",
+ "settings:app:whitelists:email:add": "Lista blanca de correos electrónicos",
+ "settings:app:whitelists:email:added": "El correo electrónico se ha agregado a la lista blanca.",
+ "settings:app:whitelists:email:description": "Esto permitirá el registro únicamente de correos electrónicos y proveedores en la lista blanca. Cualquier otro correo electrónico que intente registrarse será rechazado.",
+ "settings:app:whitelists:email:errors:format": "El Correo Electrónico no es un correo electrónico o proveedor válido (es decir: @ejemplo.es).",
+ "settings:app:whitelists:email:errors:missing": "Falta el Correo Electrónico",
+ "settings:app:whitelists:email:placeholder": "Escriba el correo electrónico aquí...",
+ "settings:app:whitelists:email:remove": "Eliminar",
+ "settings:app:whitelists:email:remove:message": "El correo electrónico será eliminado de la lista blanca.",
+ "settings:app:whitelists:email:removed": "El Correo Electrónico ha sido eliminado de la lista blanca.",
+ "settings:app:whitelists:meta:emails:label": "Correos Electrónicos permitidos",
+ "settings:app:wise": "Estas configuraciones se reflejarán en toda la plataforma.",
+ "settings:app:wise:saved": "Preferencias globales actualizadas",
+ "settings:lang": "Idioma",
+ "settings:lang:contribute": "Elija el idioma para la visualización de la aplicación. Contribuya a las traducciones en nuestro repositorio de GitHub.",
+ "settings:not:found": "No se han encontrado las configuraciones requeridas, revise su ortografía y vuelva a intentarlo",
+ "settings:theme:dark": "Modo Oscuro",
+ "settings:theme:light": "Modo Claro",
+
+ "snapp:clipboard:copied": "Snapp copiado al Portapapeles",
+ "snapp:clipboard:error": "Debes estar en un dominio HTTPS seguro y confiable para usar el Portapapeles del Navegador",
+ "snapp:disable": "Deshabilitar",
+ "snapp:has:been:enabled": "Snapp habilitado.",
+ "snapp:has:been:disabled": "Snapp deshabilitado.",
+ "snapp:disable:helper:text": "Pausa este Snapp. Se conservarán sus datos, el código corto seleccionado y los datos de visualización. El usuario recibirá un mensaje de desambiguación explicando que la redirección no está disponible temporalmente.",
+ "snapp:disable:helper:usages": "Además, cuando un snapp se utiliza la cantidad de veces establecida, se desactiva de forma predeterminada. Se puede volver a habilitar desde aquí.",
+ "snapp:is:disabled": "Solicitar Snapps no está disponible en este momento, inténtelo más tarde. Si el error persiste, intente comunicarse con el Administrador del Sistema.",
+ "snapps:usage:by:country": "Público de {{country}}",
+ "snapps:usage": "Número de visitantes: {{count}}",
+ "snapps:columns:author": "Autor",
+ "snapps:columns:created": "Creado",
+ "snapps:columns:has:secret": "Protegido",
+ "snapps:columns:max:usages": "Limitar",
+ "snapps:columns:original:url": "Origen",
+ "snapps:columns:shortcode": "Código corto",
+ "snapps:columns:status": "Estado",
+ "snapps:columns:ttl": "Cad.",
+ "snapps:columns:used": "Usos",
+ "snapps:create:one": "Crear un Snapp",
+ "snapps:created": "Snapp guardado con éxito",
+ "snapps:date:invalid": "La fecha de vencimiento tiene un formato no válido.",
+ "snapps:domain:blacklisted": "Hay un problema con el dominio del proveedor. Si cree que se trata de un error, comuníquese con el Administrador de la Aplicación.",
+ "snapps:has:secret:false": "Desprotegido",
+ "snapps:has:secret:label": "Protegido por secreto",
+ "snapps:has:secret:true": "Protegido",
+ "snapps:limit": "Has creado {{count}} de {{max}} URLs.",
+ "snapps:max:urls:reached": "Alcanzaste el límite máximo establecido para el usuario.",
+ "snapps:more:copy": "Copiar snapp",
+ "snapps:more:delete": "Borrar",
+ "snapps:more:edit": "Editar",
+ "snapps:more:qrcode": "Código QR",
+ "snapps:not:found": "No había una URL corta para esta consulta, inténtelo de nuevo. Si el error persiste, intente ponerse en contacto con el administrador del sistema.",
+ "snapps:notes:label": "Notas",
+ "snapps:original:url:description": "Escriba la URL original aquí...",
+ "snapps:original:url:helper": "Debe ser un enlace https:// válido",
+ "snapps:original:url:invalid": "La URL Original del Snapp no es una URL https segura válida.",
+ "snapps:original:url:label": "URL original",
+ "snapps:original:url:unset": "La URL Original de Snapp no está configurada.",
+ "snapps:passcode:placeholder": "Escriba aquí el secreto ...",
+ "snapps:protected": "Protegido",
+ "snapps:protected:helper": "Este snapp está protegido. Proporcione las credenciales correctas para continuar.",
+ "snapps:qrcode:download": "Descargar Código QR",
+ "snapps:reset:sort": "Restablecer filtros",
+ "snapps:secret:invalid": "Credenciales incorrectas",
+ "snapps:secret:unset": "Secreto no establecido",
+ "snapps:sections:advanced:secret": "Establecer un secreto",
+ "snapps:sections:advanced:secret:description": "Proteja este vínculo con un código secreto. Será necesario para los usuarios para poder continuar con el recurso vinculado.",
+ "snapps:sections:advanced:secret:edit:placeholder": "Editar para cambiar el código secreto...",
+ "snapps:sections:advanced:secret:label": "Secreto",
+ "snapps:sections:advanced:secret:placeholder": "Escriba el código secreto aquí...",
+ "snapps:sections:advanced:ttl": "Establecer vencimiento",
+ "snapps:sections:advanced:ttl:description": "Establezca una fecha de vencimiento para esta URL corta. Después de ese tiempo, la URL corta será eliminada.",
+ "snapps:sections:advanced:ttl:label": "Elige una fecha",
+ "snapps:sections:advanced:ttl:placeholder": "Establecer vencimiento",
+ "snapps:sections:advanced:usages": "Establecer usos máximos",
+ "snapps:sections:advanced:usages:description": "Establezca el Snapp en un máximo de usos antes de que se desactive",
+ "snapps:select:columns": "Seleccionar columnas",
+ "snapps:selected:remove": "Eliminar seleccionado",
+ "snapps:selected:remove:helper": "Estás a punto de eliminar {{ids_count}} snapps, y metadatos y métricas relativas. Esto será permanente. ¿Quieres continuar?",
+ "snapps:selected:removed": "Los Snapps deseados se han eliminado.",
+ "snapps:shortcode:description": "Escriba el código corto aquí...",
+ "snapps:shortcode:helper": "Esto se generará automáticamente si se deja en blanco",
+ "snapps:shortcode:label": "Código corto",
+ "snapps:status:active": "Activo",
+ "snapps:status:blacklisted": "En la lista negra",
+ "snapps:status:disabled": "Desactivado",
+ "snapps:status:expired": "Caducado",
+ "snapps:urls:list": "Lista de URLs",
+ "snapps:visit": "Visitar Snapp",
+ "snapps:vt:api:key:malicious": "Esta URL ha sido incluida en la lista negra de la API de VirusTotal. Si cree que se trata de un error, comuníquese con el Administrador del Sistema.",
+
+ "snapps:import": "Importar Snapps",
+ "snapps:import:sqlite:button": "Actualizar la Base de Datos",
+ "snapps:import:sqlite:modal:label": "Actualizar la Base de Datos",
+ "snapps:import:sqlite:modal:helper": "Se ha detectado un archivo SQLITE de una versión anterior. ¿Quieres intentar importar el Snapp anterior? Esta operación puede tardar mucho tiempo en bases de datos grandes.",
+ "snapps:import:helper": "Importar archivo CSV de la versión anterior de Snapp",
+ "snapps:import:label": "Cargar un archivo CSV",
+ "snapps:import:label:assign": "Asignar snapps a los usuarios",
+ "snapps:import:error": "Ha habido un error al importar. Obtenga más información en la consola del navegador.",
+ "snapps:import:error:extension": "La importación solo funciona con archivos CSV.",
+ "snapps:import:successful": "Los snapps se guardaron correctamente en la base de datos.",
+
+ "super:admin:protects": "No puedes editar o eliminar a un SuperAdministrador.",
+ "users:advanced:settings": "Ajustes Avanzados",
+ "users:advanced:settings:admin:description": "Otorga a este usuario un rol de administrador.",
+ "users:advanced:settings:admin:label": "Administrador",
+ "users:advanced:settings:admin:privilege": "Los administradores no se ven afectados por esto.",
+ "users:columns:created": "Creado",
+ "users:columns:email": "Correo-e",
+ "users:columns:roles": "Roles",
+ "users:columns:updated": "Actualizado",
+ "users:columns:urls": "URLs",
+ "users:columns:username": "Nombre de Usuario",
+ "users:create:one": "Crear usuario",
+ "users:created": "El usuario ha sido creado.",
+ "users:email:helper": "El correo electrónico del usuario nuevo creado.",
+ "users:email:label": "Correo-e",
+ "users:email:placeholder": "Escriba el correo electrónico aquí...",
+ "users:more:delete": "Borrar usuario",
+ "users:more:edit": "Editar",
+ "users:notes:helper": "Las notas solo son visibles a través de la página de usuario exclusiva de los Administradores",
+ "users:notes:label": "Notas",
+ "users:reset:sort": "Quitar Filtros",
+ "users:role:admin": "Administrador",
+ "users:role:superadmin": "Super Administrador",
+ "users:role:user": "Usuario",
+ "users:select:columns": "Seleccionar columnas",
+ "users:selected:remove": "Borrar usuario",
+ "users:selected:remove:helper": "Estás a punto de eliminar {{ids_count}} usuarios y su contenido. Esto es irreversible. ¿Quieres continuar?",
+ "users:selected:removed": "Usuario eliminado correctamente",
+ "users:updated": "El usuario ha sido actualizado.",
+ "users:username:helper": "El nombre de usuario del nuevo usuario creado.",
+ "users:username:label": "Nombre de usuario",
+ "users:username:placeholder": "Escriba el nombre de usuario aquí...",
+ "users:invite:resent": "La invitación se ha vuelto a enviar correctamente",
+
+ "home:intro": "¿Busca una solución de acortamiento de URL confiable y autohospedable? ¡No busque más! {{appname}} es la herramienta perfecta para personas y empresas que buscan control sobre la gestión de sus URL.",
+ "home:features:label": "Nuestras Funciones",
+ "home:features:ui:label": "Interfaz amigable",
+ "home:features:ui:description": "Snapp proporciona una interfaz fácil de usar para acortar enlaces sin problemas. ¡Lea cómo empezar!",
+ "home:features:auth:label": "Autentificación Segura",
+ "home:features:auth:description": "Disfrute de una experiencia segura con sesiones de autenticación y contraseñas codificadas. Su información está en buenas manos.",
+ "home:features:shortcode:label": "Códigos Cortos Personalizados",
+ "home:features:shortcode:description": "Cree códigos cortos personalizados para sus enlaces para hacerlos memorizables y fáciles de compartir.",
+ "home:features:ttl:label": "Caducidad",
+ "home:features:ttl:description": "Controla la vida útil de tus enlaces con fechas de caducidad. Establece fechas de caducidad para mayor seguridad o déjalas activas de forma indefinida.",
+ "home:features:secret:label": "Enlaces secretos",
+ "home:features:secret:description": "Agregue una capa adicional de protección con enlaces secretos. Elija compartir enlaces con un público seleccionado utilizando secretos únicos.",
+ "home:features:metrics:label": "Análisis de Uso",
+ "home:features:metrics:description": "Proporcione análisis detallados para cada enlace que cree. Snapp recopila métricas de forma anónima y proporciona información sobre la interacción de los enlaces.",
+ "home:features:integration:label": "Métricas Avanzadas",
+ "home:features:integration:description": "Integre su instancia de Snapp con su instancia Umami Analytics autohospedada o en la nube para obtener métricas avanzadas de sus Snapps.",
+ "home:features:vt:label": "Comprueba la reputación de las URL",
+ "home:features:vt:description": "Proteja los enlaces que pasan a través de su instancia de Snapp verificando su reputación en la API de VirusTotal.",
+ "home:features:rest:label": "API REST",
+ "home:features:rest:description": "Funciones solicitadas por la comunidad que permiten que API Rest endpoint cree y administre sus Snapps de forma remota. Lea los Swagger Docs completos aquí.",
+
+ "home:getting:started:label": "Primeros pasos",
+ "home:getting:started:description": "Snapp es una plataforma de código abierto autohospedable",
+
+ "home:manual:install": "Instalación manual",
+ "home:manual:install:steps": "Para ejecutar Snapp necesitas un entorno con NodeJS instalado y disponible",
+ "home:manual:install:redis": "Snapp requiere ahora una Base de Datos Redis en ejecución. Puedes usar de forma simple el compose proporcionado para ejecutar unaa instancia de Redis con persistencia.",
+ "home:manual:install:clone:0": "Clonar el repositorio de git",
+ "home:manual:install:clone:1": "git clone https://github.com/urania-dev/snapp.git",
+ "home:manual:install:download:0": "Instalar dependencias",
+ "home:manual:install:download:1": "npm install",
+ "home:manual:install:env:0": "Copie y edite el archivo .env.example",
+ "home:manual:install:env:1": "cp .env.example .env && nano .env",
+ "home:manual:install:dev:0": "Desarrolla y amplía Snapp en tu servidor
npm run dev",
+ "home:manual:install:build:0": "Crea la apiación",
+ "home:manual:install:build:1": "npm run build",
+ "home:manual:install:run:0": "¡Ejecuta y disfruta!",
+ "home:manual:install:run:1": "node -r dotenv/config build",
+ "home:docker": "Usando el Contenedor Docker",
+ "home:docker:description": "Utilice este docker-compose.yml para ejecutar su Snapp",
+ "home:docker:better": "Puede encontrar un mejor docker compose en nuestro Repositorio Github.",
+ "home:migration": "Migración",
+ "home:migration:description": "Las últimas versiones de Snapp incluyeron Exportación a CSV para facilitar la migración. Simplemente inicie sesión e importe sus URL desde el panel y continúe desde donde lo dejó.",
+
+ "home:stack:label": "The Stack",
+ "home:stack:description": "La tecnología involucrada",
+
+ "snapp:update:db": "https:// válida",
+ "snapps:original:url:invalid": "O URL orixinal do Snapp non é un URL seguro https válido.",
+ "snapps:original:url:label": "URL orixinal",
+ "snapps:original:url:unset": "O URL orixinal de Snapp non está definido.",
+ "snapps:passcode:placeholder": "Escribe aquí o segredo...",
+ "snapps:protected": "Protexido",
+ "snapps:protected:helper": "Este snapp está protexido. Introduce as credenciais correctas para continuar.",
+ "snapps:qrcode:download": "Descargar código QR",
+ "snapps:reset:sort": "Restablecer filtros",
+ "snapps:secret:invalid": "Credenciais incorrectas",
+ "snapps:secret:unset": "O segredo non está establecido",
+ "snapps:sections:advanced:secret": "Establece un segredo",
+ "snapps:sections:advanced:secret:description": "Protexa esta ligazón cun código secreto. Requiriráselle aos usuarios para poder continuar co recurso vinculado.",
+ "snapps:sections:advanced:secret:edit:placeholder": "Editar para modificar o código secreto...",
+ "snapps:sections:advanced:secret:label": "Segredo",
+ "snapps:sections:advanced:secret:placeholder": "Escribe aquí o código secreto...",
+ "snapps:sections:advanced:ttl": "Establece a caducidade",
+ "snapps:sections:advanced:ttl:description": "Establece unha caducidade para este URL curto. Despois deste tempo, o URL curto será eliminado.",
+ "snapps:sections:advanced:ttl:label": "Seleccione unha data",
+ "snapps:sections:advanced:ttl:placeholder": "Establece a caducidade",
+ "snapps:sections:advanced:usages": "Establecer usos máximos",
+ "snapps:sections:advanced:usages:description": "Establece o Snapp nun máximo de usos antes de que se desactive",
+ "snapps:select:columns": "Seleccione columnas",
+ "snapps:selected:remove": "Eliminar o seleccionado",
+ "snapps:selected:remove:helper": "Estás a piques de eliminar {{ids_count}} snapps, así como os metadatos e métricas relativos. Isto será permanente. Queres continuar?",
+ "snapps:selected:removed": "Elimináronse os Snapps desexados.",
+ "snapps:shortcode:description": "Escribe aquí o código curto...",
+ "snapps:shortcode:helper": "Se se deixa en branco, xerarase automaticamente",
+ "snapps:shortcode:label": "Código curto",
+ "snapps:status:active": "Activo",
+ "snapps:status:blacklisted": "Na lista negra",
+ "snapps:status:disabled": "Desactivado",
+ "snapps:status:expired": "Caducado",
+ "snapps:urls:list": "Lista de URLs",
+ "snapps:visit": "Visitar Snapp",
+ "snapps:vt:api:key:malicious": "Este URL foi incluído na lista negra da API de VirusTotal. Se cres que se trata dun erro, póñase en contacto co Administrador do Sistema.",
+
+ "snapps:import": "Importar Snapps",
+ "snapps:import:sqlite:button": "Actualizar a Base de Datos",
+ "snapps:import:sqlite:modal:label": "Actualizar a Base de Datos",
+ "snapps:import:sqlite:modal:helper": "Detectouse un ficheiro SQLITE dunha versión anterior. Queres probar a importar o anterior Snapp? Esta operación pode levar moito tempo para bases de datos grandes.",
+ "snapps:import:helper": "Importar ficheiros CSV desde unha versión anterior de Snapp",
+ "snapps:import:label": "Carga un ficheiro CSV",
+ "snapps:import:label:assign": "Asignar snapps a usuarios",
+ "snapps:import:error": "Produciuse un erro durante a importación. Obtén máis información na consola do navegador.",
+ "snapps:import:error:extension": "A importación só funciona con ficheiros CSV.",
+ "snapps:import:successful": "Os snapps gardáronse correctamente na base de datos",
+
+ "super:admin:protects": "Non podes editar nin eliminar un SuperAdministrador.",
+ "users:advanced:settings": "Configuración Avanzada",
+ "users:advanced:settings:admin:description": "Otorga a este usuario un rol de administrador.",
+ "users:advanced:settings:admin:label": "Administrador",
+ "users:advanced:settings:admin:privilege": "Os Administradores non se ven afectados por isto.",
+ "users:columns:created": "Creado",
+ "users:columns:email": "Correo-e",
+ "users:columns:roles": "Roles",
+ "users:columns:updated": "Actualizado",
+ "users:columns:urls": "URLs",
+ "users:columns:username": "Nome de Usuario",
+ "users:create:one": "Crear usuario",
+ "users:created": "O usuario foi creado.",
+ "users:email:helper": "O correo electrónico do usuario novo creado",
+ "users:email:label": "Correo-e",
+ "users:email:placeholder": "Escribe aquí o correo electrónico...",
+ "users:more:delete": "Eliminar usuario",
+ "users:more:edit": "Editar",
+ "users:notes:helper": "As notas só son visibles a través da páxina de usuario exclusiva dos Administradores",
+ "users:notes:label": "Notas",
+ "users:reset:sort": "Eliminar Filtros",
+ "users:role:admin": "Administrador",
+ "users:role:superadmin": "Super Administrador",
+ "users:role:user": "Usuario",
+ "users:select:columns": "Seleccione columnas",
+ "users:selected:remove": "Eliminar usuario",
+ "users:selected:remove:helper": "Estás a piques de eliminar {{ids_count}} usuarios e o seu contido. Isto é irreversible. Queres continuar?",
+ "users:selected:removed": "Usuario eliminado correctamente",
+ "users:updated": "Actualizouse o usuario.",
+ "users:username:helper": "O nome de usuario do usuario novo creado",
+ "users:username:label": "Nome de usuario",
+ "users:username:placeholder": "Escribe aquí o nome de usuario...",
+ "users:invite:resent": "A invitación volveuse a enviar correctamente",
+
+ "home:intro": "Buscas unha solución de acurtamento de URL fiable e autoaloxable? Non busques máis! {{appname}} é a ferramenta perfecta para persoas e empresas que buscan controlar a súa xestión de URL.",
+ "home:features:label": "As Nosas Características",
+ "home:features:ui:label": "Interfaz amigable",
+ "home:features:ui:description": "Snapp ofrece unha interface fácil de usar para acurtar enlaces sen problemas. Lea como comezar!",
+ "home:features:auth:label": "Autenticación Segura",
+ "home:features:auth:description": "Goza dunha experiencia segura con sesións de autenticación e contrasinais codificados. A túa información está en boas mans.",
+ "home:features:shortcode:label": "Códigos Curtos Personalizados",
+ "home:features:shortcode:description": "Crea códigos curtos personalizados para as túas ligazóns para que sexan memorizables e fáciles de compartir.",
+ "home:features:ttl:label": "Caducidade",
+ "home:features:ttl:description": "Controla a vida útil das túas ligazóns coas datas de caducidade. Establece datas de caducidade para aumentar a seguridade ou déixaas activas de forma indefinida.",
+ "home:features:secret:label": "Ligazóns secretas",
+ "home:features:secret:description": "Engade unha capa adicional de protección con ligazóns secretas. Escolle compartir ligazóns cunha audiencia seleccionada mediante segredos únicos.",
+ "home:features:metrics:label": "Analíticas de Uso",
+ "home:features:metrics:description": "Proporciona analíticas detalladas para cada ligazón que crees. Snapp reúne métricas de forma anónima, proporcionando información sobre as relacións coas ligazóns.",
+ "home:features:integration:label": "Métricas Avanzadas",
+ "home:features:integration:description": "Integre a súa instancia de Snapp coa súa instancia autoaloxada ou na nube de Umami Analytics para obter métricas avanzadas dos teus Snapps.",
+ "home:features:vt:label": "Comproba a reputación dos URL",
+ "home:features:vt:description": "Protexe as ligazóns que pasan pola túa instancia de Snapp comprobando a súa reputación na API de VirusTotal.",
+ "home:features:rest:label": "REST API",
+ "home:features:rest:description": "Funcións solicitadas pola comunidade que permiten a API Rest endpoint crear e xestionar os teus Snapps de forma remota. Lea os Swagger Docs completos aquí.",
+
+ "home:getting:started:label": "Primerios pasos",
+ "home:getting:started:description": "Snapp é unha plataforma de código aberto autoaloxable",
+
+ "home:manual:install": "Instalación manual",
+ "home:manual:install:steps": "Para executar Snapp, necesitas un entorno con NodeJS instalado e dispoñible",
+ "home:manual:install:redis": "Snapp precisa agora unha base de datos de Redis en execución. Podes usar de forma sinxela o compose proporcionado para executar a instancia de Redis con persistencia.",
+ "home:manual:install:clone:0": "Clonar o repositorio git",
+ "home:manual:install:clone:1": "git clone https://github.com/urania-dev/snapp.git",
+ "home:manual:install:download:0": "Instalar dependencias",
+ "home:manual:install:download:1": "npm install",
+ "home:manual:install:env:0": "Copia e edita o ficheiro .env.example",
+ "home:manual:install:env:1": "cp .env.example .env && nano .env",
+ "home:manual:install:dev:0": "Desenvolve e estende Snapp no teu servidor npm run dev",
+ "home:manual:install:build:0": "Crea a aplicación",
+ "home:manual:install:build:1": "npm run build",
+ "home:manual:install:run:0": "Executa e disfruta!",
+ "home:manual:install:run:1": "node -r dotenv/config build",
+ "home:docker": "Usando Docker Container",
+ "home:docker:description": "Use este docker-compose.yml para executar o seu Snapp",
+ "home:docker:better": "Podes atopar un mellor docker compose no noso Repositorio Github.",
+ "home:migration": "Migración",
+ "home:migration:description": "As versións máis recentes de Snapp incluían Exportación a CSV para facilitar a migración. Simplemente inicia sesión e importa os teus URLs dende o panel de control, e continúa onde o deixaches.",
+
+ "home:stack:label": "The Stack",
+ "home:stack:description": "A tecnoloxía implicada",
+
+ "snapp:update:db": "