diff --git a/bin/getIntl.js b/bin/getIntl.js index c9ad2649..930f7a08 100644 --- a/bin/getIntl.js +++ b/bin/getIntl.js @@ -4,12 +4,14 @@ import { DEFAULT_LOCALE, LOCALE } from '../src/routes/_static/intl.js' import enUS from '../src/intl/en-US.js' import fr from '../src/intl/fr.js' import de from '../src/intl/de.js' +import es from '../src/intl/es.js' // TODO: make it so we don't have to explicitly list these out const locales = { 'en-US': enUS, fr, - de + de, + es } const intl = locales[LOCALE] diff --git a/src/intl/es.js b/src/intl/es.js new file mode 100644 index 00000000..31aac6b3 --- /dev/null +++ b/src/intl/es.js @@ -0,0 +1,696 @@ +export default { + // Home page, basic
+ Pinafore es un cliente web para + Mastodon, + diseñado para ser rápido y sencillo. +
++ Lee el + artículo introductorio en el blog, + o comienza iniciando sesión en una instancia: +
`, + logIn: 'Iniciar sesión', + footer: ` ++ Pinafore es + software de código abierto + creado por + Nolan Lawson + y distribuido bajo la + Licencia AGPL. + Aquí está la política de privacidad. +
+ `, + // Manifest + longAppName: 'Pinafore para Mastodon', + newStatus: 'Nuevo toot', + // Generic UI + loading: 'Cargando', + okay: 'OK', + cancel: 'Cancelar', + alert: 'Alerta', + close: 'Cerrar', + error: 'Error: {error}', + errorShort: 'Error:', + // Relative timestamps + justNow: 'ahora mismo', + // Navigation, page titles + navItemLabel: ` + {label} {selected, select, + true {(página actual)} + other {} + } {name, select, + notifications {{count, plural, + =0 {} + one {(1 notificación)} + other {({count} notificaciones)} + }} + community {{count, plural, + =0 {} + one {(1 solicitud de seguimiento)} + other {({count} solicitudes de seguimiento)} + }} + other {} + } + `, + blockedUsers: 'Usuarios bloqueados', + bookmarks: 'Marcadores', + directMessages: 'Mensajes directos', + favorites: 'Favoritos', + federated: 'Federada', + home: 'Inicio', + local: 'Local', + notifications: 'Notificaciones', + mutedUsers: 'Usuarios silenciados', + pinnedStatuses: 'Toots fijados', + followRequests: 'Solicitudes de seguimiento', + followRequestsLabel: `Solicitudes de seguimiento {hasFollowRequests, select, + true {({count})} + other {} + }`, + list: 'Lista', + search: 'Buscar', + pageHeader: 'Encabezado de página', + goBack: 'Retroceder', + back: 'Atrás', + profile: 'Perfil', + federatedTimeline: 'Cronología federada', + localTimeline: 'Cronología local', + // community page + community: 'Comunidad', + pinnableTimelines: 'Cronologías que puedes fijar', + timelines: 'Cronologías', + lists: 'Listas', + instanceSettings: 'Opciones para instancia', + notificationMentions: 'Notificación de menciones', + profileWithMedia: 'Perfil con multimedia', + profileWithReplies: 'Perfil con respuestas', + hashtag: 'Hashtag', + // not logged in + profileNotLoggedIn: 'Aquí se mostrará una cronología de usuario cuando hayas iniciado sesión.', + bookmarksNotLoggedIn: 'Tus marcadores se mostrarán aquí cuando hayas iniciado sesión.', + directMessagesNotLoggedIn: 'Tus mensajes directos se mostrarán aquí cuando hayas iniciado sesión.', + favoritesNotLoggedIn: 'Tus favoritos se mostrarán aquí cuando hayas iniciado sesión.', + federatedTimelineNotLoggedIn: 'Tu cronología federada se mostrará aquí cuando hayas iniciado sesión.', + localTimelineNotLoggedIn: 'Tu cronología localse mostrará aquí cuando hayas iniciado sesión.', + searchNotLoggedIn: 'Puedes buscar una vez que inicias sesión en una instancia.', + communityNotLoggedIn: 'Las opciones para comunidad se mostrarán aquí cuando hayas iniciado sesión.', + listNotLoggedIn: 'Aquí se mostrará una lista cuando hayas iniciado sesión.', + notificationsNotLoggedIn: 'Tus notificaciones se mostrarán aquí cuando hayas iniciado sesión.', + notificationMentionsNotLoggedIn: 'Las notificaciones de tus menciones se mostrarán aquí cuando hayas iniciado sesión.', + statusNotLoggedIn: 'Aquí se mostrará un hilo de toots cuando hayas iniciado sesión.', + tagNotLoggedIn: 'Aquí se mostrará una cronología de hashtags cuando hayas iniciado sesión.', + // Notification subpages + filters: 'Filtros', + all: 'Todo', + mentions: 'Menciones', + // Follow requests + approve: 'Aceptar', + reject: 'Rechazar', + // Hotkeys + hotkeys: 'Atajos de teclado', + global: 'Globales', + timeline: 'Cronología', + media: 'Multimedia', + globalHotkeys: ` + {leftRightChangesFocus, select, + true { ++ Pinafore es + software libre y de código abierto + creado por + Nolan Lawson + y distribuido bajo la + GNU Affero General Public License. +
+ ++ Pinafore no almacena ninguna información personal en sus servidores, + incluyendo, pero no limitándose a nombres, direcciones de correo electrónico, + direcciones IP, posts y fotos. +
+ ++ Pinafore es un sitio estático. Todos los datos son almacenados en tu navegador y compartidos con las instancias del fediverso + a las que te conectas. +
+ ++ Iconos proporcionados por Font Awesome. +
+ ++ Logo gracias a "sailboat" por Gregor Cresnar, de + the Noun Project. +
`, + // Settings + settings: 'Opciones de configuración', + general: 'General', + generalSettings: 'Opciones generales', + showSensitive: 'Mostrar multimedia sensible por defecto', + showPlain: 'Mostrar un color gris liso para multimedia sensible', + allSensitive: 'Tratar todo multimedia como sensible', + largeMedia: 'Mostrar imágenes y vídeos grandes incrustados', + autoplayGifs: 'Reproducir automáticamente GIFs animados', + hideCards: 'Ocultar paneles de previsualización de enlaces', + underlineLinks: 'Subrayar enlaces en toots y perfiles', + accessibility: 'Accesibilidad', + reduceMotion: 'Reducir movimiento en animaciones de la interfaz', + disableTappable: 'Deshabilitar área para tocar en todo el toot', + removeEmoji: 'Eliminar emoji de nombres de usuario', + shortAria: 'Usar etiquetas ARIA cortas para artículos', + theme: 'Diseño visual', + themeForInstance: 'Diseño visual para {instance}', + disableCustomScrollbars: 'Deshabilitar barras deslizantes personalizadas', + bottomNav: 'Situar la barra de navegación al final de la pantalla', + centerNav: 'Centrar la barra de navegación', + preferences: 'Preferencias', + hotkeySettings: 'Opciones para atajos de teclado', + disableHotkeys: 'Deshabilitar todos los atajos de teclado', + leftRightArrows: 'Las flechas izquierda/derecha cambian el foco en vez de columnas/multimedia', + guide: 'Guía', + reload: 'Recargar', + // Wellness settings + wellness: 'Bienestar', + wellnessSettings: 'Opciones para el bienestar', + wellnessDescription: `Las opciones para el bienestar están diseñadas para reducir los aspectos que inducen adicción o ansiedad en las redes sociales. + Elige cualquier opción que vaya bien para ti.`, + enableAll: 'Habilitar todos', + metrics: 'Métricas', + hideFollowerCount: 'Ocultar recuento de seguidores (hasta 10)', + hideReblogCount: 'Ocultar recuento de reenvíos', + hideFavoriteCount: 'Ocultar recuento de favoritos', + hideUnread: 'Ocultar recuento de notificaciones sin leer (es decir, el punto rojo)', + // The quality that makes something seem important or interesting because it seems to be happening now + immediacy: 'Inmediatez', + showAbsoluteTimestamps: 'Mostrar marcas de tiempo absolutas (p.ej., "3 de marzo") en vez de marcas de tiempo relativas (p. ej., "hace 5 minutos")', + ui: 'Interfaz', + grayscaleMode: 'Modo escala de grises', + wellnessFooter: `Estas opciones están parcialmente basadas en pautas del + Center for Humane Technology.`, + // This is a link: "You can filter or disable notifications in the _instance settings_" + filterNotificationsPre: 'Puedes filtrar o deshabilitar notificaciones en', + filterNotificationsText: 'opciones para instancia', + filterNotificationsPost: '', + // Custom tooltips, like "Disable _infinite scroll_", where you can click _infinite scroll_ + // to see a description. It's hard to properly internationalize, so we just break up the strings. + disableInfiniteScrollPre: 'Deshabilitar', + disableInfiniteScrollText: 'desplazamiento infinito', + disableInfiniteScrollDescription: `Cuando el desplazamiento infinito esté deshabilitado, los nuevos toots no se mostrarán automáticamente al final o al principio de la cronología. En vez de esto, habrá botones que te permitirán + cargar más contenido a demanda.`, + disableInfiniteScrollPost: '', + // Instance settings + loggedInAs: 'Iniciaste sesión como', + homeTimelineFilters: 'Filtros para la cronología Inicio', + notificationFilters: 'Filtros para notificaciones', + pushNotifications: 'Notificaciones Push', + // Add instance page + storageError: `Parece que Pinafore no puede almacenar datos localmente. ¿Está tu navegador en modo privado + o bloqueando las cookies? Pinafore almacena todos los datos localmente, y requiere LocalStorage e + IndexedDB para funcionar correctamente.`, + javaScriptError: 'Debes habilitar JavaScript para iniciar sesión.', + enterInstanceName: 'Introducir nombre de instancia', + instanceColon: 'Instancia:', + // Custom tooltip, concatenated together + getAnInstancePre: '¿No tienes una', + getAnInstanceText: 'instancia', + getAnInstanceDescription: 'Una instancia es tu servidor de inicio de Mastodon, por ejemplo, mastodon.social o cybre.space.', + getAnInstancePost: '?', + joinMastodon: '¡Unirse a Mastodon!', + instancesYouveLoggedInTo: 'Instancias en las que has iniciado sesión:', + addAnotherInstance: 'Añadir otra instancia', + youreNotLoggedIn: 'No has iniciado sesión en ninguna instancia.', + currentInstanceLabel: `{instance} {current, select, + true {(instancia actual)} + other {} + }`, + // Link text + logInToAnInstancePre: '', + logInToAnInstanceText: 'Inicia sesión en una instancia', + logInToAnInstancePost: 'para empezar a usar Pinafore.', + // Another custom tooltip + showRingPre: 'Mostrar siempre', + showRingText: 'anillo del foco', + showRingDescription: 'El anillo del foco es el contorno que muestra el elemento que actualmente tiene el foco. Por defecto solo se muestra cuando se usa el teclado (no el ratón o un dispositivo táctil), pero puedes elegir mostrarlo siempre.', + showRingPost: '', + instances: 'Instancias', + addInstance: 'Añadir instancia', + homeTimelineFilterSettings: 'Opciones para filtros de la cronología Inicio', + showReblogs: 'Mostrar reenvíos', + showReplies: 'Mostrar respuestas', + switchOrLogOut: 'Seleccionar o cerrar sesión en esta instancia', + switchTo: 'Seleccionar esta instancia', + switchToInstance: 'Seleccionar instancia', + switchToNameOfInstance: 'Seleccionar {instance}', + logOut: 'Cerrar sesión', + logOutOfInstanceConfirm: '¿Cerrar sesión en {instance}?', + notificationFilterSettings: 'Opciones para filtros de notificaciones', + // Push notifications + browserDoesNotSupportPush: 'Tu navegador no admite notificaciones Push.', + deniedPush: 'Has denegado el permiso para mostrar notificaciones.', + pushNotificationsNote: 'Observa que solo puedes recibir notificaciones Push para una instancia al mismo tiempo.', + pushSettings: 'Opciones para notificaciones Push', + newFollowers: 'Nuevos seguidores', + reblogs: 'Reenvíos', + pollResults: 'Resultados de encuesta', + subscriptions: 'Suscripción a toots', + needToReauthenticate: 'Tienes que volver a autenticarte para habilitar las notificaciones Push. ¿Cerrr sesión en {instance}?', + failedToUpdatePush: 'Se ha producido un fallo al actualizar las opciones para notificaciones Push: {error}', + // Themes + chooseTheme: 'Elegir un diseño visual', + darkBackground: 'Fondo oscuro', + lightBackground: 'Fondo claro', + themeLabel: `{label} {default, select, + true {(por defecto)} + other {} + }`, + animatedImage: 'Imagen animada: {description}', + showImage: `Mostrar {animated, select, + true {animated} + other {} + } imagen: {description}`, + playVideoOrAudio: `Reproducir {audio, select, + true {audio} + other {vídeo} + }: {description}`, + accountFollowedYou: '{name} te siguió, {account}', + accountSignedUp: '{name} inició sesión, {account}', + accountRequestedFollow: '{name} solicitó seguirte, {account}', + accountReported: '{name} creó una denuncia, {account}', + reblogCountsHidden: 'Recuento de reenvíos oculto', + favoriteCountsHidden: 'Recuento de favoritos oculto', + rebloggedTimes: `Reenviado {count, plural, + one {1 vez} + other {{count} veces} + }`, + favoritedTimes: `Marcado como favorito {count, plural, + one {1 vez} + other {{count} veces} + }`, + pinnedStatus: 'Toot fijado', + rebloggedYou: 'reenvió tu toot', + favoritedYou: 'marcó como favorito tu toot', + followedYou: 'te siguió', + edited: 'editó su toot', + requestedFollow: 'solicitó seguirte', + reported: 'creó una denuncia', + signedUp: 'sesión iniciada', + posted: 'publicado', + pollYouCreatedEnded: 'Una encuesta que creaste ha finalizado', + pollYouVotedEnded: 'Una encuesta en la que votaste ha finalizado', + reblogged: 'reenviado', + favorited: 'marcado como favorito', + unreblogged: 'no reenviado', + unfavorited: 'no marcado como favorito', + showSensitiveMedia: 'Mostrar multimedia sensible', + hideSensitiveMedia: 'Ocultar multimedia sensible', + clickToShowSensitive: 'Contenido sensible. Haz clic para mostrar.', + longPost: 'Publicación larga', + // Accessible status labels + accountRebloggedYou: '{account} reenvió tu toot', + accountFavoritedYou: '{account} marcó como favorito tu toot', + accountEdited: '{account} editó su toot', + rebloggedByAccount: 'reenviado por {account}', + contentWarningContent: 'Advertencia de contenido: {spoiler}', + hasMedia: 'tiene multimedia', + hasPoll: 'tiene encuesta', + shortStatusLabel: '{privacy} toot de {account}', + // Privacy types + public: 'Público', + unlisted: 'No listado', + followersOnly: 'Solo seguidores', + direct: 'Directo', + // Themes + themeRoyal: 'Royal', + themeScarlet: 'Escarlata', + themeSeafoam: 'Espuma de mar', + themeHotpants: 'Hotpants', + themeOaken: 'Roble', + themeMajesty: 'Majesty', + themeGecko: 'Gecko', + themeGrayscale: 'Escala de grises', + themeOzark: 'Ozark', + themeCobalt: 'Cobalto', + themeSorcery: 'Sorcery', + themePunk: 'Punk', + themeRiot: 'Riot', + themeHacker: 'Hacker', + themeMastodon: 'Mastodon', + themePitchBlack: 'Tono negro', + themeDarkGrayscale: 'Escala de gris oscuro', + // Polls + voteOnPoll: 'Votar en encuesta', + pollChoices: 'Opciones de la encuesta', + vote: 'Votar', + pollDetails: 'Detalles de la encuesta', + refresh: 'Actualizar', + expires: 'Finaliza', + expired: 'Finalizada', + voteCount: `{count, plural, + one {1 voto} + other {{count} votos} + }`, + // Status interactions + clickToShowThread: '{time} - haz clic para mostrar el hilo', + showMore: 'Mostrar más', + showLess: 'Mostrar menos', + closeReply: 'Cerrar respuesta', + cannotReblogFollowersOnly: 'No se puede reenviar porque es solo para seguidores', + cannotReblogDirectMessage: 'No se puede reenviar porque es un mensaje directo', + reblog: 'Reenviar', + reply: 'Responder', + replyToThread: 'Responder al hilo', + favorite: 'Favorito', + unfavorite: 'No favorito', + // timeline + loadingMore: 'Cargando más…', + loadMore: 'Cargar más', + showCountMore: 'Mostrar {count} más', + nothingToShow: 'Nada para mostrar.', + // status thread page + statusThreadPage: 'Página de hilo de toots', + status: 'Toot', + // toast messages + blockedAccount: 'Cuenta bloqueada', + unblockedAccount: 'Cuenta desbloqueada', + unableToBlock: 'No se puede bloquear la cuenta: {error}', + unableToUnblock: 'No se puede desbloquear la cuenta: {error}', + bookmarkedStatus: 'Toot con marcador', + unbookmarkedStatus: 'Toot sin marcador', + unableToBookmark: 'No se puede poner marcador: {error}', + unableToUnbookmark: 'No se puede quitar marcador: {error}', + cannotPostOffline: 'No puedes publicar mientras estás sin conexión', + unableToPost: 'No se puede publicar el toot: {error}', + statusDeleted: 'Toot borrado', + unableToDelete: 'No se puede borrar el toot: {error}', + cannotFavoriteOffline: 'No puedes marcar como favorito mientras estás sin conexión', + cannotUnfavoriteOffline: 'No puedes quitar marca de favorito mientras estás sin conexión', + unableToFavorite: 'No se puede marcar como favorito: {error}', + unableToUnfavorite: 'No se puede quitar marca de favorito: {error}', + followedAccount: 'Cuenta seguida', + unfollowedAccount: 'Cuenta no seguida', + unableToFollow: 'No se puede seguir a la cuenta: {error}', + unableToUnfollow: 'No se puede dejar de seguir a la cuenta: {error}', + accessTokenRevoked: 'El token de acceso fue anulado, se cerró sesión en {instance}', + loggedOutOfInstance: 'Se cerró sesión en {instance}', + failedToUploadMedia: 'Falló la subida del multimedia: {error}', + mutedAccount: 'Cuenta silenciada', + unmutedAccount: 'Cuenta no silenciada', + unableToMute: 'No se puede silenciar la cuenta: {error}', + unableToUnmute: 'No se puede dejar de silenciar la cuenta: {error}', + mutedConversation: 'Conversación silenciada', + unmutedConversation: 'Conversación no silenciada', + unableToMuteConversation: 'No se puede silenciar la conversación: {error}', + unableToUnmuteConversation: 'No se puede dejar de silenciar la conversación: {error}', + unpinnedStatus: 'Toot no fijado', + unableToPinStatus: 'No se puede fijar el toot: {error}', + unableToUnpinStatus: 'No se puede dejar de fijar el toot: {error}', + unableToRefreshPoll: 'No se puede actualizar la encuesta: {error}', + unableToVoteInPoll: 'No se puede votar en la encuesta: {error}', + cannotReblogOffline: 'No puedes reenviar mientras estás sin conexión.', + cannotUnreblogOffline: 'No puedes deshacer reenvíos mientras estás sin conexión.', + failedToReblog: 'Fallo al reenviar: {error}', + failedToUnreblog: 'Fallo al deshacer reenvío: {error}', + submittedReport: 'Denuncia enviada', + failedToReport: 'Fallo al enviar denuncia: {error}', + approvedFollowRequest: 'Solicitud de seguimiento aceptada', + rejectedFollowRequest: 'Solicitud de seguimiento rechazada', + unableToApproveFollowRequest: 'No se puede aceptar la solicitud de seguimiento: {error}', + unableToRejectFollowRequest: 'No se puede rechazar la solicitud de seguimiento: {error}', + searchError: 'Error durante la búsqueda: {error}', + hidDomain: 'Dominio oculto', + unhidDomain: 'Dominio no oculto', + unableToHideDomain: 'No se puede ocultar el dominio: {error}', + unableToUnhideDomain: 'No se puede dejar de ocultar el dominio: {error}', + showingReblogs: 'Mostrando reenvíos', + hidingReblogs: 'Ocultando reenvíos', + unableToShowReblogs: 'No se puede mostrar los reenvíos: {error}', + unableToHideReblogs: 'No se puede ocultar los reenvíos: {error}', + unableToShare: 'No se puede compartir: {error}', + unableToSubscribe: 'Imposible suscribirse: {error}', + unableToUnsubscribe: 'Imposible dejar de suscribirse: {error}', + showingOfflineContent: 'La petición a internet falló. Mostrando contenido sin conexión.', + youAreOffline: 'Parece que estás sin conexión. Puedes leer contenido incluso sin conexión.', + // Snackbar UI + updateAvailable: 'Actualización de la aplicación disponible.', + // Word/phrase filters + wordFilters: 'Filtros de palabras', + noFilters: 'No tienes ningún filtro de palabras.', + wordOrPhrase: 'Palabra o frase', + contexts: 'Contextos', + addFilter: 'Añadir filtro', + editFilter: 'Editar filtro', + filterHome: 'Inicio y listas', + filterNotifications: 'Notificaciones', + filterPublic: 'Cronologías públicas', + filterThread: 'Conversaciones', + filterAccount: 'Perfiles', + filterUnknown: 'Desconocido', + expireAfter: 'Expira al cabo de', + whereToFilter: 'Dónde filtrar', + irreversible: 'Irreversible', + wholeWord: 'Palabra completa', + save: 'Guardar', + updatedFilter: 'Filtro actualizado', + createdFilter: 'Filtro creado', + failedToModifyFilter: 'Fallo al modificar el filtro: {error}', + deletedFilter: 'Filtro borrado', + required: 'Requerido', + // Dialogs + profileOptions: 'Opciones de perfil', + copyLink: 'Copiar enlace', + emoji: 'Emoji', + editMedia: 'Editar multimedia', + shortcutHelp: 'Ayuda sobre atajos de teclado', + statusOptions: 'Opciones de estado', + confirm: 'Confirmar', + closeDialog: 'Cerrar diálogo', + postPrivacy: 'Privacidad del post', + homeOnInstance: 'Inicio en {instance}', + statusesTimelineOnInstance: 'Estados: {timeline} cronología en {instance}', + statusesHashtag: 'Estados: #{hashtag} hashtag', + statusesThread: 'Estados: hilo', + statusesAccountTimeline: 'Estado: cronología de cuenta', + statusesList: 'Estado: lista', + notificationsOnInstance: 'Notificaciones en {instance}' +} diff --git a/webpack/client.config.js b/webpack/client.config.js index 9f7ece67..dd9a62a2 100644 --- a/webpack/client.config.js +++ b/webpack/client.config.js @@ -12,8 +12,9 @@ import urlRegex from '../src/routes/_utils/urlRegexSource.js' // TODO: make it so we don't have to list these out explicitly import fr from 'emoji-picker-element/i18n/fr.js' import de from 'emoji-picker-element/i18n/de.js' +import es from 'emoji-picker-element/i18n/es.js' -const emojiPickerLocales = { fr, de } +const emojiPickerLocales = { fr, de, es } const emojiPickerI18n = LOCALE !== DEFAULT_LOCALE && emojiPickerLocales[LOCALE]