Newer
Older
Sunfish / src / Sunfish.Core / Strings.cs
@Ivan Dominguez Ivan Dominguez 21 hours ago 11 KB 3.0
using System.Runtime.InteropServices;
using Sunfish.Shares;

namespace Sunfish;

/// <summary>Textos de usuario en espanol e ingles.</summary>
public static partial class Strings
{
    public static bool Spanish { get; private set; }

    static Strings() => Detect();

    /// <summary>SUNFISH_LANG manda; si no, el locale (LC_ALL, LC_MESSAGES, LANG) o el idioma de Windows.</summary>
    public static void Detect()
    {
        string? lang = FirstNonEmpty("SUNFISH_LANG", "LC_ALL", "LC_MESSAGES", "LANG");
        if (lang is null && OperatingSystem.IsWindows())
            lang = (GetUserDefaultUILanguage() & 0x3FF) == 0x0A ? "es" : "en";
        Spanish = lang is not null && lang.StartsWith("es", StringComparison.OrdinalIgnoreCase);
    }

    /// <summary>Fuerza el idioma ("es" o "en"), p. ej. desde --lang.</summary>
    public static void Force(string lang) =>
        Spanish = lang.StartsWith("es", StringComparison.OrdinalIgnoreCase);

    [LibraryImport("kernel32.dll")]
    private static partial ushort GetUserDefaultUILanguage();

    private static string? FirstNonEmpty(params string[] variables)
    {
        foreach (var name in variables)
        {
            var value = Environment.GetEnvironmentVariable(name);
            if (!string.IsNullOrWhiteSpace(value))
                return value;
        }
        return null;
    }

    private static string T(string english, string spanish) => Spanish ? spanish : english;

    // Web: navegador de directorios
    public static string ColName => T("Name", "Nombre");
    public static string ColSize => T("Size", "Tamaño");
    public static string ColDate => T("Date", "Fecha");
    public static string ParentFolder => T("Parent folder", "Carpeta superior");
    public static string EmptyFolder => T("(empty folder)", "(carpeta vacía)");
    public static string Shares => T("Shares", "Carpetas compartidas");
    public static string FolderContents => T("contents", "contenido");

    // Web: errores
    public static string ErrorTitle(int status) => status switch
    {
        400 => T("Bad request", "Petición incorrecta"),
        403 => T("Forbidden", "Prohibido"),
        404 => T("Not found", "No encontrado"),
        405 => T("Method not allowed", "Método no permitido"),
        416 => T("Range not satisfiable", "Rango no válido"),
        401 => T("Authentication required", "Hace falta identificarse"),
        409 => T("Conflict", "Conflicto"),
        413 => T("Too large", "Demasiado grande"),
        429 => T("Too many attempts", "Demasiados intentos"),
        507 => T("Not enough space", "No hay espacio suficiente"),
        _ => T("Server error", "Error del servidor"),
    };

    public static string ErrorText(int status) => status switch
    {
        401 => T("Enter a valid user name and password.", "Escribe un usuario y una contraseña válidos."),
        403 => T("This action is not allowed here.", "Esta acción no está permitida aquí."),
        404 => T("The requested address does not exist.", "La dirección pedida no existe."),
        429 => T("Too many failed attempts. Wait a minute and try again.", "Demasiados intentos fallidos. Espera un minuto y vuelve a probar."),
        _ => "",
    };

    // Web: acciones
    public static string Upload => T("Upload", "Subir");
    public static string UploadHint => T("Upload files (or drop them on the page)", "Subir ficheros (o suéltalos en la página)");
    public static string Uploading => T("Uploading", "Subiendo");
    public static string UploadDone => T("Upload finished", "Subida terminada");
    public static string NewFolder => T("New folder", "Nueva carpeta");
    public static string Create => T("Create", "Crear");
    public static string Rename => T("Rename", "Renombrar");
    public static string RenameShort => T("ren", "ren");
    public static string Delete => T("Delete", "Borrar");
    public static string DeleteShort => T("del", "borrar");
    public static string Cancel => T("Cancel", "Cancelar");
    public static string DownloadZip => T("Download folder as ZIP", "Descargar la carpeta en ZIP");
    public static string RenameTitle(string name) => T($"Rename {name}", $"Renombrar {name}");
    public static string NewName => T("New name:", "Nombre nuevo:");
    public static string DeleteFileQuestion(string name) =>
        T($"Delete the file {name}? This cannot be undone.", $"¿Borrar el fichero {name}? No se puede deshacer.");
    public static string DeleteFolderQuestion(string name) =>
        T($"Delete the folder {name} and everything inside it? This cannot be undone.",
          $"¿Borrar la carpeta {name} y todo su contenido? No se puede deshacer.");
    public static string BadToken => T("The form has expired. Go back, reload the page and try again.",
        "El formulario ha caducado. Vuelve atrás, recarga la página y prueba otra vez.");
    public static string ZipTooLarge => T("The folder is too large for a ZIP file (4 GB or 65535 entries).",
        "La carpeta es demasiado grande para un ZIP (4 GB o 65535 entradas).");

    public static string OpResult(FileOpResult result, string name) => result switch
    {
        FileOpResult.InvalidName => T($"'{name}' is not a valid name.", $"'{name}' no es un nombre válido."),
        FileOpResult.NotFound => T($"'{name}' does not exist.", $"'{name}' no existe."),
        FileOpResult.Exists => T($"'{name}' already exists.", $"'{name}' ya existe."),
        FileOpResult.NoSpace => T("There is not enough free space.", "No hay espacio libre suficiente."),
        FileOpResult.Conflict => T($"The upload of '{name}' got out of step; start it again.", $"La subida de '{name}' se ha desincronizado; empiézala de nuevo."),
        _ => T($"'{name}' could not be changed.", $"No se ha podido modificar '{name}'."),
    };

    // Configuracion
    public static string ConfigLine(int line, string message) =>
        T($"line {line}: {message}", $"línea {line}: {message}");
    public static string ConfigBadLine => T("not a section, comment or key = value", "no es una sección, comentario ni clave = valor");
    public static string ConfigBadBool(string key, string value) =>
        T($"{key}: '{value}' is not true/false", $"{key}: '{value}' no es true/false");
    public static string ConfigBadNumber(string key, string value) =>
        T($"{key}: '{value}' is not a valid number", $"{key}: '{value}' no es un número válido");
    public static string ConfigBadAddress(string value) =>
        T($"Bind: '{value}' is not an IP address", $"Bind: '{value}' no es una dirección IP");
    public static string ConfigBadLocation(string share, string location) =>
        T($"share '{share}': invalid Location '{location}'", $"share '{share}': Location '{location}' no válida");
    public static string ConfigDuplicateLocation(string share, string location) =>
        T($"share '{share}': Location '{location}' is already used", $"share '{share}': la Location '{location}' ya está en uso");
    public static string ConfigMissingPath(string share) =>
        T($"share '{share}': missing Path", $"share '{share}': falta Path");
    public static string ConfigUnknownSection(string name) =>
        T($"unknown section [{name}]", $"sección desconocida [{name}]");

    // Servidor
    public static string HttpListening(string endpoint) =>
        T($"HTTP listening on {endpoint}", $"HTTP escuchando en {endpoint}");
    public static string HttpStopped => T("HTTP stopped", "HTTP detenido");
    public static string ConnectionError(string remote, string message) =>
        T($"{remote}: connection error: {message}", $"{remote}: error de conexión: {message}");
    public static string FtpListening(string endpoint) =>
        T($"FTP listening on {endpoint}", $"FTP escuchando en {endpoint}");
    public static string FtpStopped => T("FTP stopped", "FTP detenido");
    public static string MdnsAnnouncing(string instance) =>
        T($"Announced on the LAN as '{instance}'", $"Anunciado en la red local como '{instance}'");
    public static string MdnsUnavailable(string message) =>
        T($"Cannot announce on the LAN (mDNS port 5353): {message}", $"No se puede anunciar en la red local (puerto mDNS 5353): {message}");
    public static string CannotListen(int port, string message) =>
        T($"Cannot listen on port {port}: {message}", $"No se puede escuchar en el puerto {port}: {message}");
    public static string ConfigReloaded => T("Configuration reloaded", "Configuración recargada");
    public static string ConfigReloadError(string error) =>
        T($"Configuration: {error}", $"Configuración: {error}");
    public static string UnknownShareKey(string key) =>
        T($"unknown option '{key}'", $"opción desconocida '{key}'");

    // Comunes a las aplicaciones (GUI y TUI)
    public static string AppShares => T("Shares", "Shares");
    public static string AppUsers => T("Users", "Usuarios");
    public static string AppLog => T("Log", "Registro");
    public static string AppStatus => T("Status", "Estado");
    public static string AppRunning => T("Running", "En marcha");
    public static string AppStopped => T("Stopped", "Parado");
    public static string AppPort => T("HTTP port", "Puerto HTTP");
    public static string AppAddresses => T("Addresses", "Direcciones");
    public static string AppNoShares => T("No shares yet. Add a folder to share it.", "Aún no hay shares. Añade una carpeta para compartirla.");
    public static string AppQuickShare(string path) =>
        T($"Quick share (not saved): {path}", $"Compartido al momento (no se guarda): {path}");
    public static string FieldName => T("Name", "Nombre");
    public static string FieldLocation => T("Location (URL path)", "Location (ruta en la URL)");
    public static string FieldPath => T("Folder", "Carpeta");
    public static string FieldIndex => T("Index document (empty: none)", "Documento índice (vacío: ninguno)");
    public static string FieldUsers => T("Users (comma separated; empty: public)", "Usuarios (separados por comas; vacío: público)");
    public static string FieldPassword => T("Password", "Contraseña");
    public static string OptEnabled => T("Enabled", "Activo");
    public static string OptListing => T("List folders", "Listar carpetas");
    public static string OptUpload => T("Upload and create folders", "Subir y crear carpetas");
    public static string OptOverwrite => T("Overwrite existing files", "Sobrescribir ficheros");
    public static string OptRename => T("Rename", "Renombrar");
    public static string OptDelete => T("Delete", "Borrar");
    public static string OptZip => T("Download folders as ZIP", "Descargar carpetas en ZIP");
    public static string WarnUploadListing => T(
        "Upload + listing: anyone can publish web pages in this share.",
        "Subir + listar: cualquiera puede publicar páginas web en este share.");
    public static string AskDeleteShare(string name) =>
        T($"Remove the share '{name}'? The folder and its files are not touched.",
          $"¿Quitar el share '{name}'? La carpeta y sus ficheros no se tocan.");
    public static string AskDeleteUser(string name) =>
        T($"Delete the user '{name}'?", $"¿Borrar el usuario '{name}'?");
    public static string ErrorNameInUse(string name) => T($"'{name}' is already in use.", $"'{name}' ya está en uso.");
    public static string ErrorBadName(string name) => T($"Invalid name: '{name}'.", $"Nombre no válido: '{name}'.");
    public static string ErrorNotAFolder(string path) => T($"Not a folder: {path}", $"No es una carpeta: {path}");
    public static string ErrorPasswordEmpty => T("The password cannot be empty.", "La contraseña no puede estar vacía.");
}