//! Lightweight i18n: one central registry (in the spirit of `icons.rs`). //! //! `EN` is the canonical list of user-visible strings; it doubles as the key //! table. `DE` and `FR` translate the same keys; a key missing from a //! translation falls back to English. //! //! - `t(key)` resolves a key for the current locale. Non-reactive — for //! toasts, event handlers, and one-shot constructions (dialogs). //! - `tr(key)` is the same as a reactive closure, for `view!` children and //! attributes, so switching the language re-renders in place. //! - `error_text(code, fallback)` maps a server error *code* to a //! translation; unknown or absent codes fall back to the server message. //! //! Parameterized strings carry exactly one `{}` placeholder; callers do //! `format!(t(k::X), arg)`. //! //! Every table is sorted by key so lookups can binary-search. //! //! Locale precedence: the signed-in user's profile setting (persisted //! server-side), else the browser language. `init` + `set_locale` drive a //! global signal so every `tr` subscriber updates. use std::sync::OnceLock; use leptos::prelude::*; use wasm_bindgen::JsCast; /// A supported UI language. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Locale { En, De, Fr, } impl Locale { pub const fn code(self) -> &'static str { match self { Locale::En => "en", Locale::De => "de", Locale::Fr => "fr", } } /// Parse a BCP-47-ish tag ("de", "de-AT", "DE") into a supported locale. pub fn from_code(code: &str) -> Option { let lang = code.split(['-', '_']).next()?.to_ascii_lowercase(); match lang.as_str() { "en" => Some(Locale::En), "de" => Some(Locale::De), "fr" => Some(Locale::Fr), _ => None, } } /// The browser's language, restricted to the supported locales. pub fn from_browser() -> Option { let lang = web_sys::window()?.navigator().language()?; Self::from_code(&lang) } } static READ: OnceLock> = OnceLock::new(); static WRITE: OnceLock> = OnceLock::new(); /// Called once during app setup, before the first UI render. pub fn init(locale: Locale) { let (read, write) = signal(locale); let _ = READ.set(read); let _ = WRITE.set(write); apply_doc_lang(locale); } pub fn set_locale(locale: Locale) { if let Some(w) = WRITE.get() { w.set(locale); } apply_doc_lang(locale); } pub fn current() -> Locale { // Tracked inside a reactive scope, so views follow a language switch; // outside one (event handlers, async tasks) a plain read, which Leptos // would otherwise warn about. let tracked = leptos::reactive::graph::Observer::get().is_some(); READ.get() .map(|r| if tracked { r.get() } else { r.get_untracked() }) .unwrap_or(Locale::En) } /// Like [`current`] but without registering a reactive dependency — for /// code that reads the locale only to compare before writing (e.g. the /// profile effect in `app.rs`), so the read cannot retrigger itself. pub fn current_untracked() -> Locale { READ.get().map(|r| r.get_untracked()).unwrap_or(Locale::En) } /// Keep `` in sync for screen readers and the browser UI. fn apply_doc_lang(locale: Locale) { if let Some(html) = web_sys::window() .and_then(|w| w.document()) .and_then(|d| d.document_element()) .and_then(|e| e.dyn_into::().ok()) { let _ = html.set_attribute("lang", locale.code()); } } /// Resolve a key for the current locale (non-reactive). pub fn t(key: &str) -> &'static str { text(key, current()) } /// Resolve a key for the current locale as a reactive closure, for use as a /// `view!` child or attribute value. pub fn tr(key: &str) -> impl Fn() -> String + Clone { move || t(key).to_string() } /// Like [`t`], but substitutes a single `{}` placeholder in the translation /// with `arg`. pub fn t_fmt(key: &str, arg: &str) -> String { t(key).replace("{}", arg) } /// Like [`t_fmt`] for translations with two placeholders, filling the first /// `{}` with `a` and the second with `b`. Positional, so a locale that needs /// the other order has to reword rather than swap. pub fn t_fmt2(key: &str, a: &str, b: &str) -> String { let s = t(key); match s.split_once("{}") { Some((head, tail)) => format!("{head}{a}{}", tail.replacen("{}", b, 1)), None => s.to_string(), } } /// Localize a server error: a known code maps to its translation, anything /// else (no code, unknown code) falls back to the server's English message. pub fn error_text(code: Option<&str>, fallback: &str) -> String { let Some(code) = code.filter(|c| find(EN, c).is_some()) else { return fallback.to_string(); }; // One-shot lookup for a toast message: no reactive context, so read the // locale untracked. text(code, current_untracked()).to_string() } fn text(key: &str, locale: Locale) -> &'static str { // Keys are compile-time constants from `k`; a miss is a bug (the unit // tests pin the tables against each other). match locale { Locale::En => find(EN, key).expect("unknown i18n key"), Locale::De => find(DE, key) .or_else(|| find(EN, key)) .expect("unknown i18n key"), Locale::Fr => find(FR, key) .or_else(|| find(EN, key)) .expect("unknown i18n key"), } } /// The tables are sorted by key, so a lookup is a binary search. The /// `tables_are_sorted` test keeps that invariant true. fn find(table: &'static [(&'static str, &'static str)], key: &str) -> Option<&'static str> { table .binary_search_by(|(k, _)| (*k).cmp(key)) .ok() .map(|i| table[i].1) } /// Declares the translation keys and the canonical English text in one /// place: one row per key, `CONST = "key" => "English"`. /// /// The `k` constants and the `EN` table are generated from the same row, so /// a key cannot exist in one without the other. Rows are sorted by key, /// because [`find`] binary-searches (`tables_are_sorted` pins that). macro_rules! i18n_keys { ($($name:ident = $key:literal => $en:expr),* $(,)?) => { /// Translation keys. Use these, never the raw strings: a typo in a /// key is a compile error, a typo in a string is a runtime panic. pub mod k { $(pub const $name: &str = $key;)* } /// Canonical English strings (key → text). The source of truth for /// which keys exist; DE and FR translate the same list. const EN: &[(&str, &str)] = &[$(($key, $en)),*]; }; } i18n_keys! { ACTIVE_CAN_SIGNIN = "active_can_signin" => "Active (can sign in)", ADD_APP_PASSWORD = "add_app_password" => "Create app password", ADD_FOLDER = "add_folder" => "Add folder…", ADD_HERE = "add_here" => "Add this folder", ADD_PASSKEY = "add_passkey" => "Add passkey", ADMINISTRATOR = "administrator" => "Administrator", ALL_SHARES = "all_shares" => "All shares", ALL_SHARES_HINT = "all_shares_hint" => "Every link on this server, grouped by the account that created it.", ALLOW_EDITING = "allow_editing" => "Allow editing (read-write)", ALLOW_RW_SHARES = "allow_rw_shares" => "Allow writable shares", ALLOW_RW_SHARES_DESC = "allow_rw_shares_desc" => "Let users create read-write share links. Off by default.", AND_MORE = "and_more" => "…and {} more", APP_PASSWORD_LABEL = "app_password_label" => "Name for this app password", APP_PASSWORD_REMOVED = "app_password_removed" => "App password revoked", APP_PASSWORD_SECRET_ONCE = "app_password_secret_once" => "Copy it now. It is never shown again.", APP_PASSWORDS = "app_passwords" => "App passwords", APP_PASSWORDS_HINT = "app_passwords_hint" => "An app password signs in to WebDAV only, never to this page. Use one per client instead of your account password.", CANCEL = "cancel" => "Cancel", CANT_DELETE_SELF = "cant_delete_self" => "You cannot delete yourself", CLOSE = "close" => "Close", CLOSE_ESC = "close_esc" => "Close (Esc)", COPIED = "copied" => "Copied", COPY = "copy" => "Copy", COPY_DAV_LINK = "copy_dav_link" => "Copy WebDAV link", COPY_HERE = "copy_here" => "Copy here", COPY_LINK = "copy_link" => "Copy link", COPY_MANUAL = "copy_manual" => "Copy the link manually", COPY_N_TO = "copy_n_to" => "Copy {} items to…", COPY_TO = "copy_to" => "Copy “{}” to…", CREATE = "create" => "Create", CREATE_ADMIN = "create_admin" => "Create admin account", CREATE_LINK = "create_link" => "Create link", CREATE_USER = "create_user" => "Create user", CREATING = "creating" => "Creating…", CT_TYPE_CELL = "ct_type_cell" => "mobile", CT_TYPE_FAX = "ct_type_fax" => "fax", CT_TYPE_HOME = "ct_type_home" => "home", CT_TYPE_OTHER = "ct_type_other" => "other", CT_TYPE_WORK = "ct_type_work" => "work", CUSTOM = "custom" => "Custom…", DEFAULT_ROOT_DESC = "default_root_desc" => "Open this folder on page load and on the home link.", DEFAULT_ROOT_LABEL = "default_root_label" => "Default folder", DEFAULT_ROOT_NONE = "default_root_none" => "Folder overview", DELETE = "delete" => "Delete", DELETE_ALL = "delete_all" => "Delete all", DELETE_ALL_MSG = "delete_all_msg" => "Delete all {} share links? Anyone holding them loses access. This cannot be undone.", DELETE_ALL_TITLE = "delete_all_title" => "Delete all shares?", DELETE_ALL_USER_MSG = "delete_all_user_msg" => "Delete every share link of “{}”? Anyone holding them loses access. This cannot be undone.", DELETE_FOLDER_MSG = "delete_folder_msg" => "Delete folder “{}” and everything inside it?\nThis cannot be undone.", DELETE_MSG = "delete_msg" => "Delete “{}”?\nThis cannot be undone.", DELETE_N_MSG = "delete_n_msg" => "Delete {} items?\nThis cannot be undone.", DELETE_PARTIAL = "delete_partial" => "{} of {} shares could not be deleted", DELETE_SHARE = "delete_share" => "Delete share", DELETE_USER = "delete_user" => "Delete user", DELETE_USER_CONFIRM = "delete_user_confirm" => "Delete user “{}”? This cannot be undone.", DELETED = "deleted" => "Deleted", DELETED_N_SHARES = "deleted_n_shares" => "Deleted {} shares", DISCARD = "discard" => "Discard", DISCARD_QUESTION = "discard_question" => "Discard your changes and close the editor?", DISMISS = "dismiss" => "Dismiss", DISMISS_ERROR = "dismiss_error" => "Dismiss error", DONE = "done" => "Done", DOWNLOAD = "download" => "Download", DOWNLOAD_FORMATS_MSG = "download_formats_msg" => "Choose an archive format for the folder.", DOWNLOAD_STARTED = "download_started" => "Download started", DOWNLOAD_TITLE = "download_title" => "Download “{}”", EDIT = "edit" => "Edit", EDIT_USER_TITLE = "edit_user_title" => "Edit “{}”", EMPTY_FOLDER = "empty_folder" => "This folder is empty.", ERR_ADMIN_ONLY = "err_admin_only" => "admin only", ERR_ALREADY_SET_UP = "err_already_set_up" => "server is already set up", ERR_APP_PASSWORD_LIMIT = "err_app_password_limit" => "This account already has as many app passwords as it may.", ERR_APP_PASSWORD_NOT_FOUND = "err_app_password_not_found" => "No such app password.", ERR_BAD_ACTION = "err_bad_action" => "expected action=content", ERR_BAD_BODY = "err_bad_body" => "invalid request body", ERR_BAD_EXPIRES_AT = "err_bad_expires_at" => "the expiry date is invalid", ERR_BAD_FORMAT = "err_bad_format" => "format must be one of: zip, tar, tar.gz, tar.zst", ERR_BAD_MULTIPART = "err_bad_multipart" => "expected multipart/form-data with a boundary", ERR_BAD_PART_NAME = "err_bad_part_name" => "invalid part name", ERR_BAD_POST = "err_bad_post" => "POST expects a multipart upload, a JSON mutation, or ?action=mkdir/create-file", ERR_BAD_UPLOAD = "err_bad_upload" => "invalid upload data", ERR_BAD_UPLOAD_PATH = "err_bad_upload_path" => "invalid file path in upload", ERR_CHALLENGE_EXPIRED = "err_challenge_expired" => "That took too long, please try again.", ERR_DEFAULT_CALENDAR = "err_default_calendar" => "The calendar that receives invitations cannot be deleted.", ERR_DST_REQUIRED = "err_dst_required" => "dst_root_id is required", ERR_FILE_NAME_REQUIRED = "err_file_name_required" => "a file name is required", ERR_FILES_EXIST = "err_files_exist" => "some files already exist", ERR_FOLDER_EXISTS = "err_folder_exists" => "a folder with this name already exists", ERR_FOLDER_NAME_REQUIRED = "err_folder_name_required" => "a folder name is required", ERR_FS_CONFLICT = "err_fs_conflict" => "already exists", ERR_FS_FORBIDDEN = "err_fs_forbidden" => "access denied", ERR_FS_NOT_A_DIR = "err_fs_not_a_dir" => "not a folder", ERR_FS_NOT_FOUND = "err_fs_not_found" => "folder not found", ERR_FS_ROOT_MISSING = "err_fs_root_missing" => "the configured folder no longer exists", ERR_INTERNAL = "err_internal" => "internal error", ERR_INVALID_CREDENTIALS = "err_invalid_credentials" => "invalid name or password", ERR_INVALID_DEFAULT_ROOT = "err_invalid_default_root" => "the default folder is not one of your folders", ERR_INVALID_LANGUAGE = "err_invalid_language" => "invalid language tag", ERR_INVALID_WEEK_START = "err_invalid_week_start" => "invalid week start", ERR_LAST_ADMIN = "err_last_admin" => "cannot remove the last active admin", ERR_LAST_ADMIN_DELETE = "err_last_admin_delete" => "cannot delete the last active admin", ERR_LOCKED_OUT = "err_locked_out" => "That would leave the account with no way to sign in.", ERR_MODE_NEEDS_PASSKEY = "err_mode_needs_passkey" => "Add a passkey before requiring both.", ERR_MODE_NEEDS_PASSWORD = "err_mode_needs_password" => "Set a password before requiring both.", ERR_NAME_LENGTH = "err_name_length" => "name must be 1–64 characters", ERR_NEW_NAME_REQUIRED = "err_new_name_required" => "new_name is required", ERR_NO_FILES_UPLOADED = "err_no_files_uploaded" => "no files were uploaded", ERR_NO_SUCH_FOLDER = "err_no_such_folder" => "no such folder", ERR_NOT_A_FILE = "err_not_a_file" => "not a file", ERR_NOT_SIGNED_IN = "err_not_signed_in" => "not signed in", ERR_OWN_ACCOUNT = "err_own_account" => "you cannot disable your own account", ERR_OWN_ADMIN = "err_own_admin" => "you cannot remove your own admin rights", ERR_OWN_DELETE = "err_own_delete" => "you cannot delete your own account", ERR_PART_NO_NAME = "err_part_no_name" => "part without a name", ERR_PASSKEY_DUPLICATE = "err_passkey_duplicate" => "That passkey is already registered.", ERR_PASSKEY_FAILED = "err_passkey_failed" => "That passkey could not be used.", ERR_PASSKEY_LAST_CREDENTIAL = "err_passkey_last_credential" => "Set a password before removing your last passkey.", ERR_PASSKEY_LIMIT = "err_passkey_limit" => "This account already has as many passkeys as it may.", ERR_PASSKEY_MALFORMED = "err_passkey_malformed" => "The browser sent unreadable data.", ERR_PASSKEY_NOT_FOUND = "err_passkey_not_found" => "No such passkey.", ERR_PASSKEY_ORIGIN = "err_passkey_origin" => "Passkeys are set up for a different address.", ERR_PASSKEY_UNAVAILABLE = "err_passkey_unavailable" => "Passkeys are not available here.", ERR_PASSWORD_LAST_CREDENTIAL = "err_password_last_credential" => "Add a passkey before removing your password.", ERR_PASSWORD_SHORT = "err_password_short" => "password must be at least 8 characters", ERR_PATH_REQUIRED = "err_path_required" => "a path inside the folder is required", ERR_READ_ONLY_FOLDER = "err_read_only_folder" => "read-only folder", ERR_REQUIRED_BY_MODE = "err_required_by_mode" => "This account requires a password and a passkey.", ERR_ROOT_FORBIDDEN = "err_root_forbidden" => "root not accessible", ERR_RW_RO_FOLDER = "err_rw_ro_folder" => "this folder is read-only for you, so it cannot be shared writably", ERR_RW_SHARES_DISABLED = "err_rw_shares_disabled" => "writable shares are disabled", ERR_SAVE_FAILED = "err_save_failed" => "could not save the file", ERR_SEARCH_BAD_SCOPE = "err_search_bad_scope" => "scope must be name, content or both", ERR_SEARCH_FORBIDDEN = "err_search_forbidden" => "search requires a signed-in session", ERR_SESSION_EXPIRED = "err_session_expired" => "session expired, please sign in again", ERR_SHARE_EXPIRED = "err_share_expired" => "this share has expired", ERR_SHARE_LOCKED = "err_share_locked" => "This share is password protected.", ERR_SHARE_NO_PASSWORD = "err_share_no_password" => "This share has no password.", ERR_SHARE_NOT_FOUND = "err_share_not_found" => "share not found", ERR_SHARE_TOKEN_FORBIDDEN = "err_share_token_forbidden" => "a share token cannot be used here; sign in instead", ERR_SHARE_WRONG_PASSWORD = "err_share_wrong_password" => "Wrong password.", ERR_TOO_LARGE_PREVIEW = "err_too_large_preview" => "file too large to preview", ERR_TOO_LARGE_SAVE = "err_too_large_save" => "file too large to save", ERR_USER_EXISTS = "err_user_exists" => "a user with that name already exists", ERR_USER_NOT_FOUND = "err_user_not_found" => "user not found", EXCLUDE_DUP_ERR = "exclude_dup_err" => "That folder is already excluded.", EXCLUDE_FOLDER = "exclude_folder" => "Exclude folder…", EXCLUDE_HERE = "exclude_here" => "Exclude this folder", EXCLUDE_ROOT_ERR = "exclude_root_err" => "The whole root cannot be excluded; that would turn search off.", EXPIRES = "expires" => "Expires", EXPIRES_AT = "expires_at" => "Expires {}", EXPIRY_1D = "expiry_1d" => "1 day", EXPIRY_1H = "expiry_1h" => "1 hour", EXPIRY_1MO = "expiry_1mo" => "1 month", EXPIRY_1W = "expiry_1w" => "1 week", FILE = "file" => "File", FILE_CHANGED = "file_changed" => "File changed on disk", FILE_CREATED = "file_created" => "File created", FILE_INFO = "file_info" => "File info", FILE_NAME = "file_name" => "File name", FILE_NOT_FOUND = "file_not_found" => "File not found", FILES = "files" => "Files", FMT_TAR = "fmt_tar" => "Tar", FMT_TARGZ = "fmt_targz" => "Tar + gzip", FMT_TARZST = "fmt_tarzst" => "Tar + zstd", FMT_ZIP = "fmt_zip" => "Zip", FOLDER = "folder" => "Folder", FOLDER_CREATED = "folder_created" => "Folder created", FOLDER_GONE_MSG = "folder_gone_msg" => "This folder is no longer accessible. Choose another one from the sidebar.", FOLDER_GONE_TITLE = "folder_gone_title" => "Folder not available", FOLDER_NAME = "folder_name" => "Folder name", FOLDERS = "folders" => "Folders", FOLDERS_PATHS_HINT = "folders_paths_hint" => "Paths are relative to the server root. “.” is the whole root.", GRID_VIEW = "grid_view" => "Grid view", INFO = "info" => "Info", KEEP_EDITING = "keep_editing" => "Keep editing", LANG_AUTO = "lang_auto" => "Automatic", LANG_DE = "lang_de" => "German", LANG_EN = "lang_en" => "English", LANG_FR = "lang_fr" => "French", LANGUAGE = "language" => "Language", LANGUAGE_DESC = "language_desc" => "The interface language. Automatic uses your browser's language.", LINK_COPIED = "link_copied" => "Link copied to clipboard", LIST_VIEW = "list_view" => "List view", LOAD_LATEST = "load_latest" => "Load latest", LOADING = "loading" => "Loading…", LOADING_SHARE = "loading_share" => "Loading share…", LOCATION = "location" => "Location", LOG_OUT = "log_out" => "Log out", LOGIN_SUBTITLE = "login_subtitle" => "Sign in to continue.", MANAGE = "manage" => "Manage", MENU = "menu" => "Menu", META_CREATED = "meta_created" => "created {}", META_EXPIRES = "meta_expires" => "expires {}", MODE_RO = "mode_ro" => "read-only", MODE_RW = "mode_rw" => "read-write", MODIFIED = "modified" => "Modified", MODIFIED_AFTER = "modified_after" => "This file was modified after you opened it. “Load latest” discards your unsaved changes; “Overwrite” keeps your version.", MORE_ACTIONS = "more_actions" => "More actions", MOVE = "move" => "Move", MOVE_HERE = "move_here" => "Move here", MOVE_N_TO = "move_n_to" => "Move {} items to…", MOVE_TO = "move_to" => "Move “{}” to…", MOVED = "moved" => "Moved", NAME = "name" => "Name", NAME_TAKEN = "name_taken" => "Name already in use", NEED_FOLDER = "need_folder" => "Give the user at least one folder.", NEVER = "never" => "Never", NEVER_EXPIRES = "never_expires" => "Never expires", NEW_FILE = "new_file" => "New file", NEW_FOLDER = "new_folder" => "New folder", NEW_NAME = "new_name" => "New name", NEW_PASSWORD = "new_password" => "New password", NEW_PASSWORD_HINT = "new_password_hint" => "Leave empty to keep your current password.", NEW_PASSWORD_KEEP = "new_password_keep" => "New password (leave blank to keep)", NEW_USER = "new_user" => "New user", NO_APP_PASSWORDS = "no_app_passwords" => "No app passwords.", NO_FOLDERS_MSG = "no_folders_msg" => "An administrator hasn't assigned you any folders yet.", NO_FOLDERS_TITLE = "no_folders_title" => "No folders available", NO_PASSKEYS = "no_passkeys" => "No passkeys yet.", NO_PASSWORD_SET = "no_password_set" => "This account signs in with passkeys only.", NO_PREVIEW = "no_preview" => "No preview available", NO_PREVIEW_MSG = "no_preview_msg" => "The app can’t display “{}” here.", NO_SHARES = "no_shares" => "No shares yet", NO_SUBFOLDERS = "no_subfolders" => "No subfolders", NO_USERS = "no_users" => "No users.", OPEN = "open" => "Open", OPEN_IN_NEW_TAB = "open_in_new_tab" => "Open in new tab", OPEN_MENU = "open_menu" => "Open menu", OR_LABEL = "or_label" => "or", OVERWRITE = "overwrite" => "Overwrite", OVERWRITE_QUESTION = "overwrite_question" => "The following files already exist. Overwrite them?", PAGE_FIRST = "page_first" => "First page", PAGE_GOTO = "page_goto" => "Page", PAGE_LAST = "page_last" => "Last page", PAGE_NEXT = "page_next" => "Next page", PAGE_PREV = "page_prev" => "Previous page", PAGE_SIZE = "page_size" => "Entries per page", PAGE_SIZE_N = "page_size_n" => "{} per page", PASSKEY_ADDED = "passkey_added" => "Passkey added", PASSKEY_ADDED_ON = "passkey_added_on" => "Added {}", PASSKEY_LABEL = "passkey_label" => "Name for this passkey", PASSKEY_LAST_USED = "passkey_last_used" => "Last used {}", PASSKEY_NEEDS_NAME = "passkey_needs_name" => "Needs your user name", PASSKEY_NEEDS_NAME_HINT = "passkey_needs_name_hint" => "This passkey is not stored on the authenticator itself, so the server has to look it up. Type your user name on the sign-in page before using it.", PASSKEY_NEVER_USED = "passkey_never_used" => "Never used", PASSKEY_NOT_USED = "passkey_not_used" => "No passkey was used.", PASSKEY_REMOVED = "passkey_removed" => "Passkey removed", PASSKEY_UNSUPPORTED = "passkey_unsupported" => "This browser cannot use passkeys.", PASSKEYS = "passkeys" => "Passkeys", PASSKEYS_HINT = "passkeys_hint" => "A passkey signs you in with your fingerprint, your face or a security key.", PASSWORD = "password" => "Password", PASSWORD_MIN_HINT = "password_min_hint" => "at least 8 characters", PASSWORD_REMOVED = "password_removed" => "Password removed", PASSWORD_RESETS_SIGNIN = "password_resets_signin" => "Setting a password also deletes this account's passkeys and drops any two-factor requirement.", PIM_ACCEPT = "pim_accept" => "Accept", PIM_ACCESS = "pim_access" => "Access", PIM_ADD = "pim_add" => "Add", PIM_ADDRESS = "pim_address" => "Address for apps", PIM_ADDRESS_BOOK = "pim_address_book" => "Address book", PIM_ADDRESS_BOOKS = "pim_address_books" => "Address books", PIM_AGENDA = "pim_agenda" => "Agenda", PIM_ALL_DAY = "pim_all_day" => "All day", PIM_ALL_EVENTS = "pim_all_events" => "All events of the series", PIM_ANNIVERSARY = "pim_anniversary" => "Anniversary", PIM_APP_PASSWORDS = "pim_app_passwords" => "Create an app password", PIM_ATTENDEES = "pim_attendees" => "Attendees", PIM_AUTO = "pim_auto" => "automatic", PIM_BACK = "pim_back" => "Back", PIM_BIRTHDAY = "pim_birthday" => "Birthday", PIM_BIRTHDAYS = "pim_birthdays" => "Birthdays", PIM_CALENDAR = "pim_calendar" => "Calendar", PIM_CALENDARS = "pim_calendars" => "Calendars", PIM_CANCELLED = "pim_cancelled" => "Cancelled", PIM_CATEGORIES = "pim_categories" => "Categories", PIM_CLIENTS = "pim_clients" => "Apps", PIM_COLLECTION_URLS = "pim_collection_urls" => "Addresses of single calendars and address books", PIM_COLOR = "pim_color" => "Color", PIM_CONNECT = "pim_connect" => "Connect an app", PIM_CONNECT_TITLE = "pim_connect_title" => "Connect a calendar or contacts app", PIM_CONTACTS = "pim_contacts" => "Contacts", PIM_CREATED = "pim_created" => "Created", PIM_CUSTOM_COLOR = "pim_custom_color" => "Custom color", PIM_DECLINE = "pim_decline" => "Decline", PIM_DEFAULT_HINT = "pim_default_hint" => "This calendar receives invitations. It cannot be deleted.", PIM_DELETE_MSG = "pim_delete_msg" => "Everything in it is deleted. The attendees of your meetings get a cancellation.", PIM_DELETE_TITLE = "pim_delete_title" => "Delete “{}”?", PIM_DESCRIPTION = "pim_description" => "Description", PIM_DETAIL = "pim_detail" => "Details", PIM_DETAIL_BUSY = "pim_detail_busy" => "Busy times only", PIM_DETAIL_FULL = "pim_detail_full" => "All details", PIM_DIRECTORY = "pim_directory" => "Directory", PIM_EMAIL = "pim_email" => "Email", PIM_EXPORT = "pim_export" => "Export", PIM_FEEDS = "pim_feeds" => "Calendar and contact feeds", PIM_FEEDS_HINT = "pim_feeds_hint" => "Every public calendar and address book link on this server.", PIM_FILE = "pim_file" => "File", PIM_FROM_ORGANIZER = "pim_from_organizer" => "From {}", PIM_FROM_TIME = "pim_from_time" => "from {}", PIM_GENERAL = "pim_general" => "General", PIM_GENERATED_HINT = "pim_generated_hint" => "The server fills this in. It is read-only.", PIM_GROUP = "pim_group" => "Group", PIM_HIDE = "pim_hide" => "Hide", PIM_HINT_APPLE = "pim_hint_apple" => "Apple: add a CalDAV and a CardDAV account with the server address. Apple needs HTTPS.", PIM_HINT_DAVX5 = "pim_hint_davx5" => "Android: in DAVx⁵, sign in with URL and user name, and use the server address.", PIM_HINT_GNOME = "pim_hint_gnome" => "GNOME and Evolution: add a CalDAV or WebDAV account with the server address.", PIM_HINT_THUNDERBIRD = "pim_hint_thunderbird" => "Thunderbird: add a network calendar with the server address. Set its email identity to “None”, or it sends no invitations.", PIM_IMPORT = "pim_import" => "Import", PIM_IMPORT_DONE = "pim_import_done" => "{} new, {} updated.", PIM_IMPORT_FILE = "pim_import_file" => "Import file…", PIM_IMPORT_HINT_CAL = "pim_import_hint_cal" => "Add the events of an .ics file to this calendar. An event that is already here is updated.", PIM_IMPORT_HINT_CARDS = "pim_import_hint_cards" => "Add the contacts of a .vcf file to this address book. A contact that is already here is updated.", PIM_IMPORT_NEW_HINT_CAL = "pim_import_new_hint_cal" => "Creates a calendar with the events of an .ics file.", PIM_IMPORT_NEW_HINT_CARDS = "pim_import_new_hint_cards" => "Creates an address book with the contacts of a .vcf file.", PIM_IMPORT_NOTHING = "pim_import_nothing" => "Nothing could be imported, so nothing was created.", PIM_IMPORT_SKIPPED = "pim_import_skipped" => "{} skipped:", PIM_IMPORTED_AS = "pim_imported_as" => "Imported as “{}”.", PIM_IMPORTING = "pim_importing" => "Importing…", PIM_INV_SERIES_HINT = "pim_inv_series_hint" => "Your answer applies to the whole series.", PIM_INVITATIONS = "pim_invitations" => "Invitations", PIM_KIND_RESOURCE = "pim_kind_resource" => "Resource", PIM_KIND_ROOM = "pim_kind_room" => "Room", PIM_LINK = "pim_link" => "Link", PIM_LINK_BUSY = "pim_link_busy" => "busy times only", PIM_LINK_FULL = "pim_link_full" => "all details", PIM_LINK_REVOKED = "pim_link_revoked" => "Link revoked", PIM_LINKS = "pim_links" => "Public links", PIM_LINKS_HINT = "pim_links_hint" => "Anyone with the link can subscribe. Some calendars, such as Google Calendar and Outlook.com, need a link without a password.", PIM_LINKS_HINT_CARDS = "pim_links_hint_cards" => "Anyone with the link can download the contacts once. Apps do not follow changes.", PIM_LOCATION = "pim_location" => "Location", PIM_MANAGE = "pim_manage" => "Settings", PIM_MANAGE_OF = "pim_manage_of" => "Settings for {}", PIM_MEMBERS = "pim_members" => "Members", PIM_MODE_RO = "pim_mode_ro" => "Read only", PIM_MODE_RW = "pim_mode_rw" => "Read and write", PIM_MODE_SCHEDULE = "pim_mode_schedule" => "Read, write and send invitations", PIM_MONTH = "pim_month" => "Month", PIM_MORE_N = "pim_more_n" => "+{} more", PIM_NAME_FROM_FILE = "pim_name_from_file" => "From the file if empty", PIM_NAV = "pim_nav" => "Calendar & contacts", PIM_NEW_ADDRESS_BOOK = "pim_new_address_book" => "New address book", PIM_NEW_BOOK_FROM_FILE = "pim_new_book_from_file" => "New address book from file", PIM_NEW_CALENDAR = "pim_new_calendar" => "New calendar", PIM_NEW_CALENDAR_FROM_FILE = "pim_new_calendar_from_file" => "New calendar from file", PIM_NEW_FROM_FILE = "pim_new_from_file" => "New from file…", PIM_NEW_ROOM = "pim_new_room" => "New room", PIM_NEXT_MONTH = "pim_next_month" => "Next month", PIM_NO_CONTACTS = "pim_no_contacts" => "No contacts yet. Add some with a contacts app or an import.", PIM_NO_EVENTS_AGENDA = "pim_no_events_agenda" => "No events in the next 7 days.", PIM_NO_EVENTS_DAY = "pim_no_events_day" => "No events on this day.", PIM_NO_FEEDS = "pim_no_feeds" => "No public feeds.", PIM_NO_INVITATIONS = "pim_no_invitations" => "No open invitations.", PIM_NO_LINKS = "pim_no_links" => "No public links.", PIM_NO_MATCH = "pim_no_match" => "No contact matches.", PIM_NO_ROOMS = "pim_no_rooms" => "No rooms or resources.", PIM_NO_SHARES = "pim_no_shares" => "Not shared with anyone.", PIM_NO_TITLE = "pim_no_title" => "(no title)", PIM_NOT_CONTACT = "pim_not_contact" => "This entry is not a contact.", PIM_NOT_EVENT = "pim_not_event" => "This entry is not an event.", PIM_NOTE = "pim_note" => "Note", PIM_OPTIONAL = "pim_optional" => "optional", PIM_ORGANIZER = "pim_organizer" => "Organizer", PIM_PASSWORD_HINT = "pim_password_hint" => "Use an app password rather than your account password.", PIM_PHONE = "pim_phone" => "Phone", PIM_PICK_CONTACT = "pim_pick_contact" => "Choose a contact to see the details.", PIM_POSTAL = "pim_postal" => "Address", PIM_PREV_MONTH = "pim_prev_month" => "Previous month", PIM_PS_ACCEPTED = "pim_ps_accepted" => "Accepted", PIM_PS_DECLINED = "pim_ps_declined" => "Declined", PIM_PS_DELEGATED = "pim_ps_delegated" => "Delegated", PIM_PS_NEEDS_ACTION = "pim_ps_needs_action" => "No answer yet", PIM_PS_TENTATIVE = "pim_ps_tentative" => "Maybe", PIM_REMOVE_FROM_LIST = "pim_remove_from_list" => "Remove from my list", PIM_REMOVE_MSG = "pim_remove_msg" => "You no longer see it. The owner can share it again.", PIM_REMOVED = "pim_removed" => "Removed from your list", PIM_REPEATS = "pim_repeats" => "Repeats", PIM_REPLIED = "pim_replied" => "Answer sent", PIM_ROOM_DELETE_CONFIRM = "pim_room_delete_confirm" => "Delete “{}”? Its bookings are lost.", PIM_ROOM_DISPLAY = "pim_room_display" => "Display name", PIM_ROOM_NAME = "pim_room_name" => "Name (part of its address, cannot change)", PIM_ROOMS = "pim_rooms" => "Rooms and resources", PIM_ROOMS_HINT = "pim_rooms_hint" => "Rooms and resources can be invited to meetings. They accept free times and decline busy ones on their own.", PIM_RRULE_DAILY = "pim_rrule_daily" => "Every day", PIM_RRULE_DAILY_N = "pim_rrule_daily_n" => "Every {} days", PIM_RRULE_MONTHLY = "pim_rrule_monthly" => "Every month", PIM_RRULE_MONTHLY_N = "pim_rrule_monthly_n" => "Every {} months", PIM_RRULE_WEEKLY = "pim_rrule_weekly" => "Every week", PIM_RRULE_WEEKLY_N = "pim_rrule_weekly_n" => "Every {} weeks", PIM_RRULE_YEARLY = "pim_rrule_yearly" => "Every year", PIM_RRULE_YEARLY_N = "pim_rrule_yearly_n" => "Every {} years", PIM_SAVE_ERR = "pim_save_err" => "Could not save: {}", PIM_SEARCH_CONTACTS = "pim_search_contacts" => "Search contacts", PIM_SERVER_ADDRESS = "pim_server_address" => "Server address", PIM_SERVER_ADDRESS_HINT = "pim_server_address_hint" => "If an app does not find the server, use this address:", PIM_SHARED_BY = "pim_shared_by" => "Shared by {}", PIM_SHARED_OK = "pim_shared_ok" => "Shared with {}", PIM_SHARED_WITH_ME = "pim_shared_with_me" => "Shared with me", PIM_SHARING = "pim_sharing" => "Sharing", PIM_SHARING_HINT = "pim_sharing_hint" => "Share with another account on this server.", PIM_SHOW = "pim_show" => "Show", PIM_SHOW_ALL = "pim_show_all" => "Show all", PIM_SHOW_ONLY = "pim_show_only" => "Show only this one", PIM_SKIP_COMPONENT = "pim_skip_component" => "this type is not accepted here", PIM_SKIP_INVALID = "pim_skip_invalid" => "invalid or incomplete data", PIM_SKIP_SIZE = "pim_skip_size" => "too large", PIM_SKIP_UID = "pim_skip_uid" => "the same UID is already in another calendar", PIM_SUBSCRIBE = "pim_subscribe" => "Subscribe", PIM_TENTATIVE = "pim_tentative" => "Maybe", PIM_THIS_EVENT = "pim_this_event" => "Only this event", PIM_TODAY = "pim_today" => "Today", PIM_TRANSPARENT = "pim_transparent" => "Show as free: events do not block time slots in invitations", PIM_TRUNCATED = "pim_truncated" => "Not every event fits into this view. Hide some calendars to see the rest.", PIM_UNSHARE = "pim_unshare" => "Stop sharing", PIM_UNSHARED = "pim_unshared" => "No longer shared", PIM_UNTIL_TIME = "pim_until_time" => "until {}", PIM_UPCOMING = "pim_upcoming" => "Next 7 days", PIM_USER = "pim_user" => "User name", PIM_USER_NAME = "pim_user_name" => "User name", PIM_WEBSITE = "pim_website" => "Website", PIM_WHEN = "pim_when" => "When", PIM_YOUR_ANSWER = "pim_your_answer" => "Your answer", PROFILE = "profile" => "Profile", PROFILE_SAVE_ERR = "profile_save_err" => "Could not save profile: {}", PROFILE_SAVED = "profile_saved" => "Profile saved", PW_SHORT = "pw_short" => "Password must be at least 8 characters.", READ_ONLY_BADGE = "read_only_badge" => "Read-only", READ_ONLY_HINT = "read_only_hint" => "Read-only folder", REFRESH = "refresh" => "Refresh", REFRESH_FOLDERS = "refresh_folders" => "Refresh your folders", REMOVE_FOLDER = "remove_folder" => "Remove folder", REMOVE_PASSWORD = "remove_password" => "Remove password", REMOVE_PASSWORD_DESC = "remove_password_desc" => "Sign in with passkeys only. Needs at least one passkey.", RENAME = "rename" => "Rename", RENAME_TITLE = "rename_title" => "Rename “{}”", RENAMED = "renamed" => "Renamed", REPEAT_PASSWORD = "repeat_password" => "Repeat password", RETRY = "retry" => "Retry", ROOT_DUP_ERR = "root_dup_err" => "That folder is already in the list.", RW_DISABLED = "rw_disabled" => "Writable shares are disabled by the server.", RW_RO_FOLDER = "rw_ro_folder" => "This folder is read-only, so the share is read-only too.", SAVE = "save" => "Save", SAVE_PROFILE = "save_profile" => "Save profile", SAVE_SETTINGS = "save_settings" => "Save settings", SAVED = "saved" => "Saved", SAVING = "saving" => "Saving…", SEARCH = "search" => "Search", SEARCH_BOTH = "search_both" => "Both", SEARCH_COLLAPSE_ALL = "search_collapse_all" => "Collapse all", SEARCH_CONTENT = "search_content" => "Content", SEARCH_EXCLUDES = "search_excludes" => "Excluded from search", SEARCH_EXCLUDES_EMPTY = "search_excludes_empty" => "No folders are excluded.", SEARCH_EXPAND_ALL = "search_expand_all" => "Expand all", SEARCH_FAILED = "search_failed" => "The search failed.", SEARCH_GOTO = "search_goto" => "Show in folder", SEARCH_HERE = "search_here" => "Search here", SEARCH_IN = "search_in" => "Search in…", SEARCH_IN_FOLDER = "search_in_folder" => "Search in this folder", SEARCH_IN_N_FILES = "search_in_n_files" => "in {} files", SEARCH_N_MATCHES = "search_n_matches" => "{} matches", SEARCH_N_RESULTS = "search_n_results" => "{} results", SEARCH_NAME = "search_name" => "Name", SEARCH_NO_RESULTS = "search_no_results" => "no results", SEARCH_PLACEHOLDER = "search_placeholder" => "Search files and their contents", SEARCH_RUN = "search_run" => "Search", SEARCH_SCANNED = "search_scanned" => "scanned {} files", SEARCH_SHOW_MORE = "search_show_more" => "Show {} more", SEARCH_SHOWN_OF = "search_shown_of" => "Showing {} of {}", SEARCH_SKIPPED = "search_skipped" => "{} skipped (over 10 MiB)", SEARCH_STOP = "search_stop" => "Stop", SEARCH_STOPPED = "search_stopped" => "stopped · {} results", SEARCH_TOOK = "search_took" => "{} ms", SEARCHING = "searching" => "searching…", SECOND_FACTOR_PASSKEY = "second_factor_passkey" => "Now confirm with your passkey.", SECOND_FACTOR_PASSWORD = "second_factor_password" => "Enter the password for {}.", SECURITY = "security" => "Security", SELECT_FOLDER_MSG = "select_folder_msg" => "Choose a folder from the sidebar to start browsing.", SELECT_FOLDER_TITLE = "select_folder_title" => "Select a folder", SERVER = "server" => "Server", SERVER_ROOT = "server_root" => "Server root", SERVER_UNREACHABLE = "server_unreachable" => "The server is not reachable.", SETTINGS = "settings" => "Settings", SETTINGS_SAVE_ERR = "settings_save_err" => "Could not save settings: {}", SETTINGS_SAVED = "settings_saved" => "Settings saved", SETUP_INTRO = "setup_intro" => "First boot: create the admin account. This user can manage other users and server settings.", SETUP_PW_MISMATCH = "setup_pw_mismatch" => "Passwords don't match.", SHARE = "share" => "Share", SHARE_CREATE_ERR = "share_create_err" => "Could not create share: {}", SHARE_DELETE_ERR = "share_delete_err" => "Could not delete share", SHARE_DELETED = "share_deleted" => "Share deleted", SHARE_DIALOG_HINT = "share_dialog_hint" => "Create a link for this item. Writable links let viewers upload and edit.", SHARE_EXPIRED = "share_expired" => "Share expired", SHARE_EXPIRED_MSG = "share_expired_msg" => "This share link is no longer active.", SHARE_LINK = "share_link" => "Share link", SHARE_LOCKED_TITLE = "share_locked_title" => "Password required", SHARE_NOT_FOUND = "share_not_found" => "Share not found", SHARE_NOT_FOUND_MSG = "share_not_found_msg" => "This link is invalid or the share was removed.", SHARE_OWNER_DISABLED = "share_owner_disabled" => "deactivated account", SHARE_PASSWORD_HINT = "share_password_hint" => "Optional. Visitors must enter it before the share opens, at least 8 characters.", SHARE_PERM_RO = "share_perm_ro" => "Anyone with this link can read “{}”.", SHARE_PERM_RW = "share_perm_rw" => "Anyone with this link can read and write “{}”.", SHARE_PROTECTED = "share_protected" => "Password protected", SHARE_TITLE = "share_title" => "Share {}", SHARES = "shares" => "Shares", SHARES_DELETE_ERR = "shares_delete_err" => "Could not delete shares", SHARES_EMPTY_HINT = "shares_empty_hint" => "Right-click a file or folder and choose “Share” to create a link.", SHARES_VIEW_HINT = "shares_view_hint" => "Links you created. Right-click a file or folder and choose “Share” to add one.", SIGN_IN = "sign_in" => "Sign in", SIGNIN_BOTH = "signin_both" => "Password and passkey", SIGNIN_BOTH_DESC = "signin_both_desc" => "Both are required. WebDAV then needs an app password, because a mount can only send a password.", SIGNIN_EITHER = "signin_either" => "Password or passkey", SIGNIN_EITHER_DESC = "signin_either_desc" => "Either one on its own signs you in.", SIGNIN_REQUIREMENT = "signin_requirement" => "Sign-in requirement", SINGLE_CLICK_DESC = "single_click_desc" => "When on, a single click opens an entry and Ctrl+click selects it. When off, a single click selects and a double click opens.", SINGLE_CLICK_LABEL = "single_click_label" => "Use single click to open", SIZE = "size" => "Size", SOME_FILES_EXIST = "some_files_exist" => "Some files already exist", SORT_ASC = "sort_asc" => "Ascending", SORT_BY = "sort_by" => "Sort by", SORT_DESC = "sort_desc" => "Descending", THEME_AUTO = "theme_auto" => "Auto", THEME_DARK = "theme_dark" => "Dark", THEME_LIGHT = "theme_light" => "Light", THEME_TITLE = "theme_title" => "Theme: {} (click to switch)", THUMBNAILS_DESC = "thumbnails_desc" => "Show a small preview instead of an icon for images and videos in grid view.", THUMBNAILS_LABEL = "thumbnails_label" => "Show thumbnails", TYPE = "type" => "Type", UNLOCK = "unlock" => "Open share", UNSAVED_CHANGES = "unsaved_changes" => "Unsaved changes", UNTIL = "until" => "Until", UPLOAD_ABORT = "upload_abort" => "Abort", UPLOAD_ABORTED = "upload_aborted" => "Aborted", UPLOAD_ACTIVE_N = "upload_active_n" => "{} active", UPLOAD_APPLY_ALL = "upload_apply_all" => "Apply to files that appear during the upload", UPLOAD_CHECK_FAILED = "upload_check_failed" => "Could not check for existing files: {}", UPLOAD_CLEAR = "upload_clear" => "Remove from list", UPLOAD_CLEAR_FINISHED = "upload_clear_finished" => "Clear finished", UPLOAD_COLLAPSE = "upload_collapse" => "Collapse", UPLOAD_COMPLETE = "upload_complete" => "Upload complete", UPLOAD_CONFLICT_QUESTION = "upload_conflict_question" => "The following files already exist. Overwrite or skip them?", UPLOAD_DROP_HINT = "upload_drop_hint" => "Drop to upload here", UPLOAD_ERRORS_N = "upload_errors_n" => "{} failed", UPLOAD_EXISTS_ASK = "upload_exists_ask" => "“{}” appeared on the server during the upload.", UPLOAD_EXPAND = "upload_expand" => "Expand", UPLOAD_FAILED = "upload_failed" => "Failed", UPLOAD_FILES = "upload_files" => "Upload files", UPLOAD_FOLDER = "upload_folder" => "Upload folder", UPLOAD_N_FILES = "upload_n_files" => "{} files", UPLOAD_PAUSE = "upload_pause" => "Pause", UPLOAD_PAUSED = "upload_paused" => "Paused", UPLOAD_PREPARING = "upload_preparing" => "Preparing…", UPLOAD_RESUME = "upload_resume" => "Resume", UPLOAD_SHOW_GRAPH = "upload_show_graph" => "Details and speed graph", UPLOAD_SKIP = "upload_skip" => "Skip", UPLOAD_SKIPPED_N = "upload_skipped_n" => "{} skipped", UPLOAD_SPEED = "upload_speed" => "{}/s", UPLOAD_WAITING = "upload_waiting" => "Waiting for your answer", UPLOADS = "uploads" => "Uploads", UPLOADS_EMPTY = "uploads_empty" => "No uploads yet", USE_PASSKEY = "use_passkey" => "Use a passkey", USE_PASSKEY_HINT = "use_passkey_hint" => "Leave the name empty unless your passkey needs it.", USER_CREATED = "user_created" => "User created", USER_DELETE_ERR = "user_delete_err" => "Could not delete user", USER_DISABLED = "user_disabled" => "disabled", USER_NAME_EXAMPLE = "user_name_example" => "e.g. alice", USER_SAVE_ERR = "user_save_err" => "Could not save user: {}", USER_UPDATED = "user_updated" => "User updated", USER_YOU = "user_you" => "(you)", USERS = "users" => "Users", WEEK_MONDAY = "week_monday" => "Monday", WEEK_SATURDAY = "week_saturday" => "Saturday", WEEK_START = "week_start" => "Week starts on", WEEK_START_DESC = "week_start_desc" => "The first day of the week in the calendar.", WEEK_SUNDAY = "week_sunday" => "Sunday", YOUR_SHARES = "your_shares" => "Your shares", } /// German translations. const DE: &[(&str, &str)] = &[ ("active_can_signin", "Aktiv (kann sich anmelden)"), ("add_app_password", "App-Passwort erstellen"), ("add_folder", "Ordner hinzufügen…"), ("add_here", "Diesen Ordner hinzufügen"), ("add_passkey", "Passkey hinzufügen"), ("administrator", "Administrator"), ("all_shares", "Alle Freigaben"), ( "all_shares_hint", "Jeder Link auf diesem Server, gruppiert nach dem Konto, das ihn erstellt hat.", ), ("allow_editing", "Bearbeitung erlauben (lesen/schreiben)"), ("allow_rw_shares", "Schreibbare Freigaben erlauben"), ( "allow_rw_shares_desc", "Benutzern erlauben, schreibbare Freigabelinks zu erstellen. Standardmäßig aus.", ), ("and_more", "…und {} weitere"), ("app_password_label", "Name für dieses App-Passwort"), ("app_password_removed", "App-Passwort widerrufen"), ( "app_password_secret_once", "Jetzt kopieren. Es wird nie wieder angezeigt.", ), ("app_passwords", "App-Passwörter"), ( "app_passwords_hint", "Ein App-Passwort gilt nur für WebDAV, nicht für diese Seite. Nutze pro Client eines statt deines Kontopassworts.", ), ("cancel", "Abbrechen"), ("cant_delete_self", "Sie können sich nicht selbst löschen"), ("close", "Schließen"), ("close_esc", "Schließen (Esc)"), ("copied", "Kopiert"), ("copy", "Kopieren"), ("copy_dav_link", "WebDAV-Link kopieren"), ("copy_here", "Hierher kopieren"), ("copy_link", "Link kopieren"), ("copy_manual", "Link manuell kopieren"), ("copy_n_to", "{} Elemente kopieren nach…"), ("copy_to", "„{}“ kopieren nach…"), ("create", "Erstellen"), ("create_admin", "Administrator-Konto erstellen"), ("create_link", "Link erstellen"), ("create_user", "Benutzer erstellen"), ("creating", "Wird erstellt…"), ("ct_type_cell", "mobil"), ("ct_type_fax", "Fax"), ("ct_type_home", "privat"), ("ct_type_other", "andere"), ("ct_type_work", "geschäftlich"), ("custom", "Benutzerdefiniert…"), ( "default_root_desc", "Diesen Ordner beim Laden der Seite und über den Home-Link öffnen.", ), ("default_root_label", "Standardordner"), ("default_root_none", "Ordnerübersicht"), ("delete", "Löschen"), ("delete_all", "Alle löschen"), ( "delete_all_msg", "Alle {} Freigabelinks löschen? Jeder, der sie besitzt, verliert den Zugriff. Das kann nicht rückgängig gemacht werden.", ), ("delete_all_title", "Alle Freigaben löschen?"), ( "delete_all_user_msg", "Alle Freigabelinks von „{}“ löschen? Jeder, der sie besitzt, verliert den Zugriff. Das kann nicht rückgängig gemacht werden.", ), ( "delete_folder_msg", "Ordner „{}“ mit allem Inhalt löschen?\nDas kann nicht rückgängig gemacht werden.", ), ( "delete_msg", "„{}“ löschen?\nDas kann nicht rückgängig gemacht werden.", ), ( "delete_n_msg", "{} Elemente löschen?\nDas kann nicht rückgängig gemacht werden.", ), ( "delete_partial", "{} von {} Freigaben konnten nicht gelöscht werden", ), ("delete_share", "Freigabe löschen"), ("delete_user", "Benutzer löschen"), ( "delete_user_confirm", "Benutzer „{}“ löschen? Das kann nicht rückgängig gemacht werden.", ), ("deleted", "Gelöscht"), ("deleted_n_shares", "{} Freigabe(n) gelöscht"), ("discard", "Verwerfen"), ( "discard_question", "Änderungen verwerfen und den Editor schließen?", ), ("dismiss", "Ausblenden"), ("dismiss_error", "Fehler ausblenden"), ("done", "Fertig"), ("download", "Herunterladen"), ( "download_formats_msg", "Archivformat für den Ordner wählen.", ), ("download_started", "Download gestartet"), ("download_title", "„{}“ herunterladen"), ("edit", "Bearbeiten"), ("edit_user_title", "„{}“ bearbeiten"), ("empty_folder", "Dieser Ordner ist leer."), (k::ERR_ADMIN_ONLY, "nur für Administratoren"), (k::ERR_ALREADY_SET_UP, "Server ist bereits eingerichtet"), ( k::ERR_APP_PASSWORD_LIMIT, "Dieses Konto hat bereits so viele App-Passwörter, wie es haben darf.", ), (k::ERR_APP_PASSWORD_NOT_FOUND, "Kein solches App-Passwort."), (k::ERR_BAD_ACTION, "action=content erwartet"), (k::ERR_BAD_BODY, "ungültiger Anfrageinhalt"), (k::ERR_BAD_EXPIRES_AT, "das Ablaufdatum ist ungültig"), ( k::ERR_BAD_FORMAT, "das Format muss eines der folgenden sein: zip, tar, tar.gz, tar.zst", ), ( k::ERR_BAD_MULTIPART, "multipart/form-data mit Boundary erwartet", ), (k::ERR_BAD_PART_NAME, "ungültiger Part-Name"), ( k::ERR_BAD_POST, "POST erwartet einen Multipart-Upload, eine JSON-Mutation oder ?action=mkdir/create-file", ), (k::ERR_BAD_UPLOAD, "ungültige Upload-Daten"), (k::ERR_BAD_UPLOAD_PATH, "ungültiger Dateipfad im Upload"), ( k::ERR_CHALLENGE_EXPIRED, "Das hat zu lange gedauert. Bitte erneut versuchen.", ), ( k::ERR_DEFAULT_CALENDAR, "Der Kalender, der Einladungen empfängt, kann nicht gelöscht werden.", ), (k::ERR_DST_REQUIRED, "dst_root_id ist erforderlich"), (k::ERR_FILE_NAME_REQUIRED, "ein Dateiname ist erforderlich"), (k::ERR_FILES_EXIST, "einige Dateien existieren bereits"), ( k::ERR_FOLDER_EXISTS, "ein Ordner mit diesem Namen existiert bereits", ), ( k::ERR_FOLDER_NAME_REQUIRED, "ein Ordnername ist erforderlich", ), (k::ERR_FS_CONFLICT, "existiert bereits"), (k::ERR_FS_FORBIDDEN, "Zugriff verweigert"), (k::ERR_FS_NOT_A_DIR, "kein Ordner"), (k::ERR_FS_NOT_FOUND, "Ordner nicht gefunden"), ( k::ERR_FS_ROOT_MISSING, "der konfigurierte Ordner existiert nicht mehr", ), (k::ERR_INTERNAL, "interner Fehler"), (k::ERR_INVALID_CREDENTIALS, "Name oder Passwort ungültig"), ( k::ERR_INVALID_DEFAULT_ROOT, "Der Standardordner gehört nicht zu Ihren Ordnern", ), (k::ERR_INVALID_LANGUAGE, "ungültiges Sprachkürzel"), (k::ERR_INVALID_WEEK_START, "ungültiger Wochenbeginn"), ( k::ERR_LAST_ADMIN, "der letzte aktive Administrator kann nicht entfernt werden", ), ( k::ERR_LAST_ADMIN_DELETE, "der letzte aktive Administrator kann nicht gelöscht werden", ), ( k::ERR_LOCKED_OUT, "Dann hätte das Konto keine Anmeldemöglichkeit mehr.", ), ( k::ERR_MODE_NEEDS_PASSKEY, "Fügen Sie einen Passkey hinzu, bevor Sie beides verlangen.", ), ( k::ERR_MODE_NEEDS_PASSWORD, "Setzen Sie ein Passwort, bevor Sie beides verlangen.", ), (k::ERR_NAME_LENGTH, "der Name muss 1–64 Zeichen haben"), (k::ERR_NEW_NAME_REQUIRED, "new_name ist erforderlich"), (k::ERR_NO_FILES_UPLOADED, "keine Dateien hochgeladen"), (k::ERR_NO_SUCH_FOLDER, "dieser Ordner existiert nicht"), (k::ERR_NOT_A_FILE, "keine Datei"), (k::ERR_NOT_SIGNED_IN, "nicht angemeldet"), ( k::ERR_OWN_ACCOUNT, "Sie können Ihr eigenes Konto nicht deaktivieren", ), ( k::ERR_OWN_ADMIN, "Sie können Ihre eigenen Administratorrechte nicht entfernen", ), ( k::ERR_OWN_DELETE, "Sie können Ihr eigenes Konto nicht löschen", ), (k::ERR_PART_NO_NAME, "Part ohne Namen"), ( k::ERR_PASSKEY_DUPLICATE, "Dieser Passkey ist bereits registriert.", ), ( k::ERR_PASSKEY_FAILED, "Dieser Passkey konnte nicht verwendet werden.", ), ( k::ERR_PASSKEY_LAST_CREDENTIAL, "Setzen Sie ein Passwort, bevor Sie den letzten Passkey entfernen.", ), ( k::ERR_PASSKEY_LIMIT, "Dieses Konto hat bereits so viele Passkeys wie erlaubt.", ), ( k::ERR_PASSKEY_MALFORMED, "Der Browser hat unlesbare Daten gesendet.", ), (k::ERR_PASSKEY_NOT_FOUND, "Passkey nicht gefunden."), ( k::ERR_PASSKEY_ORIGIN, "Passkeys sind für eine andere Adresse eingerichtet.", ), ( k::ERR_PASSKEY_UNAVAILABLE, "Passkeys sind hier nicht verfügbar.", ), ( k::ERR_PASSWORD_LAST_CREDENTIAL, "Fügen Sie einen Passkey hinzu, bevor Sie das Passwort entfernen.", ), ( k::ERR_PASSWORD_SHORT, "das Passwort muss mindestens 8 Zeichen lang sein", ), ( k::ERR_PATH_REQUIRED, "ein Pfad innerhalb des Ordners ist erforderlich", ), (k::ERR_READ_ONLY_FOLDER, "schreibgeschützter Ordner"), ( k::ERR_REQUIRED_BY_MODE, "Dieses Konto verlangt Passwort und Passkey.", ), (k::ERR_ROOT_FORBIDDEN, "kein Zugriff auf diesen Ordner"), ( k::ERR_RW_RO_FOLDER, "dieser Ordner ist für Sie schreibgeschützt und kann nicht schreibbar freigegeben werden", ), ( k::ERR_RW_SHARES_DISABLED, "schreibbare Freigaben sind deaktiviert", ), ( k::ERR_SAVE_FAILED, "die Datei konnte nicht gespeichert werden", ), ( k::ERR_SEARCH_BAD_SCOPE, "Bereich muss name, content oder both sein", ), ( k::ERR_SEARCH_FORBIDDEN, "Suche erfordert eine angemeldete Sitzung", ), ( k::ERR_SESSION_EXPIRED, "Sitzung abgelaufen, bitte erneut anmelden", ), (k::ERR_SHARE_EXPIRED, "diese Freigabe ist abgelaufen"), (k::ERR_SHARE_LOCKED, "Diese Freigabe ist passwortgeschützt."), ( k::ERR_SHARE_NO_PASSWORD, "Diese Freigabe hat kein Passwort.", ), (k::ERR_SHARE_NOT_FOUND, "Freigabe nicht gefunden"), ( k::ERR_SHARE_TOKEN_FORBIDDEN, "ein Freigabetoken kann hier nicht verwendet werden; bitte anmelden", ), (k::ERR_SHARE_WRONG_PASSWORD, "Falsches Passwort."), (k::ERR_TOO_LARGE_PREVIEW, "Datei zu groß für eine Vorschau"), (k::ERR_TOO_LARGE_SAVE, "Datei zu groß zum Speichern"), ( k::ERR_USER_EXISTS, "ein Benutzer mit diesem Namen existiert bereits", ), (k::ERR_USER_NOT_FOUND, "Benutzer nicht gefunden"), ( "exclude_dup_err", "Dieser Ordner ist bereits ausgeschlossen.", ), ("exclude_folder", "Ordner ausschließen…"), ("exclude_here", "Diesen Ordner ausschließen"), ( "exclude_root_err", "Das gesamte Stammverzeichnis kann nicht ausgeschlossen werden; das würde die Suche abschalten.", ), ("expires", "Läuft ab"), ("expires_at", "Läuft ab: {}"), ("expiry_1d", "1 Tag"), ("expiry_1h", "1 Stunde"), ("expiry_1mo", "1 Monat"), ("expiry_1w", "1 Woche"), ("file", "Datei"), ("file_changed", "Datei auf der Festplatte geändert"), ("file_created", "Datei erstellt"), ("file_info", "Datei-Info"), ("file_name", "Dateiname"), ("file_not_found", "Datei nicht gefunden"), ("files", "Dateien"), ("fmt_tar", "Tar"), ("fmt_targz", "Tar + gzip"), ("fmt_tarzst", "Tar + zstd"), ("fmt_zip", "Zip"), ("folder", "Ordner"), ("folder_created", "Ordner erstellt"), ( "folder_gone_msg", "Dieser Ordner ist nicht mehr verfügbar. Wählen Sie links einen anderen aus.", ), ("folder_gone_title", "Ordner nicht verfügbar"), ("folder_name", "Ordnername"), ("folders", "Ordner"), ( "folders_paths_hint", "Pfade sind relativ zur Serverwurzel. „.“ ist der gesamte Wurzelordner.", ), ("grid_view", "Kachelansicht"), ("info", "Info"), ("keep_editing", "Weiter bearbeiten"), ("lang_auto", "Automatisch"), ("lang_de", "Deutsch"), ("lang_en", "Englisch"), ("lang_fr", "Französisch"), ("language", "Sprache"), ( "language_desc", "Die Sprache der Benutzeroberfläche. „Automatisch“ verwendet die Sprache Ihres Browsers.", ), ("link_copied", "Link in die Zwischenablage kopiert"), ("list_view", "Listenansicht"), ("load_latest", "Neueste Version laden"), ("loading", "Wird geladen…"), ("loading_share", "Freigabe wird geladen…"), ("location", "Ort"), ("log_out", "Abmelden"), ("login_subtitle", "Anmelden, um fortzufahren."), ("manage", "Verwalten"), ("menu", "Menü"), ("meta_created", "erstellt: {}"), ("meta_expires", "läuft ab: {}"), ("mode_ro", "nur lesen"), ("mode_rw", "lesen/schreiben"), ("modified", "Geändert"), ( "modified_after", "Diese Datei wurde nach dem Öffnen geändert. „Neueste Version laden“ verwirft Ihre ungespeicherten Änderungen; „Überschreiben“ behält Ihre Version bei.", ), ("more_actions", "Weitere Aktionen"), ("move", "Verschieben"), ("move_here", "Hierher verschieben"), ("move_n_to", "{} Elemente verschieben nach…"), ("move_to", "„{}“ verschieben nach…"), ("moved", "Verschoben"), ("name", "Name"), ("name_taken", "Name wird bereits verwendet"), ( "need_folder", "Dem Benutzer muss mindestens ein Ordner zugewiesen werden.", ), ("never", "Nie"), ("never_expires", "Läuft nie ab"), ("new_file", "Neue Datei"), ("new_folder", "Neuer Ordner"), ("new_name", "Neuer Name"), ("new_password", "Neues Passwort"), ( "new_password_hint", "Leer lassen, um das aktuelle Passwort zu behalten.", ), ( "new_password_keep", "Neues Passwort (leer lassen, um beizubehalten)", ), ("new_user", "Neuer Benutzer"), ("no_app_passwords", "Keine App-Passwörter."), ( "no_folders_msg", "Ein Administrator hat Ihnen noch keine Ordner zugewiesen.", ), ("no_folders_title", "Keine Ordner verfügbar"), ("no_passkeys", "Noch keine Passkeys."), ( "no_password_set", "Dieses Konto meldet sich nur mit Passkeys an.", ), ("no_preview", "Keine Vorschau verfügbar"), ("no_preview_msg", "Die App kann „{}“ hier nicht anzeigen."), ("no_shares", "Noch keine Freigaben"), ("no_subfolders", "Keine Unterordner"), ("no_users", "Keine Benutzer."), ("open", "Öffnen"), ("open_in_new_tab", "In neuem Tab öffnen"), ("open_menu", "Menü öffnen"), ("or_label", "oder"), ("overwrite", "Überschreiben"), ( "overwrite_question", "Die folgenden Dateien existieren bereits. Überschreiben?", ), ("page_first", "Erste Seite"), ("page_goto", "Seite"), ("page_last", "Letzte Seite"), ("page_next", "Nächste Seite"), ("page_prev", "Vorherige Seite"), ("page_size", "Einträge pro Seite"), ("page_size_n", "{} pro Seite"), ("passkey_added", "Passkey hinzugefügt"), ("passkey_added_on", "Hinzugefügt {}"), ("passkey_label", "Name für diesen Passkey"), ("passkey_last_used", "Zuletzt benutzt {}"), ("passkey_needs_name", "Braucht Ihren Benutzernamen"), ( "passkey_needs_name_hint", "Dieser Passkey liegt nicht im Authenticator selbst, der Server muss ihn nachschlagen. Geben Sie Ihren Benutzernamen auf der Anmeldeseite ein, bevor Sie ihn verwenden.", ), ("passkey_never_used", "Nie benutzt"), ("passkey_not_used", "Es wurde kein Passkey verwendet."), ("passkey_removed", "Passkey entfernt"), ( "passkey_unsupported", "Dieser Browser kann keine Passkeys verwenden.", ), ("passkeys", "Passkeys"), ( "passkeys_hint", "Ein Passkey meldet Sie mit Fingerabdruck, Gesicht oder Sicherheitsschlüssel an.", ), ("password", "Passwort"), ("password_min_hint", "mindestens 8 Zeichen"), ("password_removed", "Passwort entfernt"), ( "password_resets_signin", "Ein neues Passwort löscht auch die Passkeys dieses Kontos und hebt eine Zwei-Faktor-Pflicht auf.", ), ("pim_accept", "Zusagen"), ("pim_access", "Zugriff"), ("pim_add", "Hinzufügen"), ("pim_address", "Adresse für Apps"), ("pim_address_book", "Adressbuch"), ("pim_address_books", "Adressbücher"), ("pim_agenda", "Liste"), ("pim_all_day", "Ganztägig"), ("pim_all_events", "Alle Termine der Serie"), ("pim_anniversary", "Jahrestag"), ("pim_app_passwords", "App-Passwort erstellen"), ("pim_attendees", "Teilnehmer"), ("pim_auto", "automatisch"), ("pim_back", "Zurück"), ("pim_birthday", "Geburtstag"), ("pim_birthdays", "Geburtstage"), ("pim_calendar", "Kalender"), ("pim_calendars", "Kalender"), ("pim_cancelled", "Abgesagt"), ("pim_categories", "Kategorien"), ("pim_clients", "Apps"), ( "pim_collection_urls", "Adressen einzelner Kalender und Adressbücher", ), ("pim_color", "Farbe"), ("pim_connect", "App verbinden"), ("pim_connect_title", "Kalender- oder Kontakte-App verbinden"), ("pim_contacts", "Kontakte"), ("pim_created", "Erstellt"), ("pim_custom_color", "Eigene Farbe"), ("pim_decline", "Absagen"), ( "pim_default_hint", "Dieser Kalender empfängt Einladungen. Er kann nicht gelöscht werden.", ), ( "pim_delete_msg", "Alles darin wird gelöscht. Die Teilnehmer Ihrer Termine erhalten eine Absage.", ), ("pim_delete_title", "„{}“ löschen?"), ("pim_description", "Beschreibung"), ("pim_detail", "Details"), ("pim_detail_busy", "Nur belegte Zeiten"), ("pim_detail_full", "Alle Details"), ("pim_directory", "Verzeichnis"), ("pim_email", "E-Mail"), ("pim_export", "Exportieren"), ("pim_feeds", "Kalender- und Kontakt-Feeds"), ( "pim_feeds_hint", "Jeder öffentliche Kalender- und Adressbuch-Link auf diesem Server.", ), ("pim_file", "Datei"), ("pim_from_organizer", "Von {}"), ("pim_from_time", "ab {}"), ("pim_general", "Allgemein"), ( "pim_generated_hint", "Der Server füllt dies aus. Es ist schreibgeschützt.", ), ("pim_group", "Gruppe"), ("pim_hide", "Ausblenden"), ( "pim_hint_apple", "Apple: Fügen Sie ein CalDAV- und ein CardDAV-Konto mit der Serveradresse hinzu. Apple braucht HTTPS.", ), ( "pim_hint_davx5", "Android: Melden Sie sich in DAVx⁵ mit URL und Benutzername an und nutzen Sie die Serveradresse.", ), ( "pim_hint_gnome", "GNOME und Evolution: Fügen Sie ein CalDAV- oder WebDAV-Konto mit der Serveradresse hinzu.", ), ( "pim_hint_thunderbird", "Thunderbird: Fügen Sie einen Netzwerkkalender mit der Serveradresse hinzu. Setzen Sie seine E-Mail-Identität auf „Keine“, sonst verschickt er keine Einladungen.", ), ("pim_import", "Importieren"), ("pim_import_done", "{} neu, {} aktualisiert."), ("pim_import_file", "Datei importieren…"), ( "pim_import_hint_cal", "Fügt die Termine einer .ics-Datei zu diesem Kalender hinzu. Ein Termin, der schon da ist, wird aktualisiert.", ), ( "pim_import_hint_cards", "Fügt die Kontakte einer .vcf-Datei zu diesem Adressbuch hinzu. Ein Kontakt, der schon da ist, wird aktualisiert.", ), ( "pim_import_new_hint_cal", "Legt einen Kalender mit den Terminen einer .ics-Datei an.", ), ( "pim_import_new_hint_cards", "Legt ein Adressbuch mit den Kontakten einer .vcf-Datei an.", ), ( "pim_import_nothing", "Nichts ließ sich importieren, daher wurde nichts angelegt.", ), ("pim_import_skipped", "{} übersprungen:"), ("pim_imported_as", "Importiert als „{}“."), ("pim_importing", "Importiere…"), ( "pim_inv_series_hint", "Ihre Antwort gilt für die ganze Serie.", ), ("pim_invitations", "Einladungen"), ("pim_kind_resource", "Ressource"), ("pim_kind_room", "Raum"), ("pim_link", "Link"), ("pim_link_busy", "nur belegte Zeiten"), ("pim_link_full", "alle Details"), ("pim_link_revoked", "Link widerrufen"), ("pim_links", "Öffentliche Links"), ( "pim_links_hint", "Jeder mit dem Link kann ihn abonnieren. Manche Kalender, z. B. Google Kalender und Outlook.com, brauchen einen Link ohne Passwort.", ), ( "pim_links_hint_cards", "Jeder mit dem Link kann die Kontakte einmal herunterladen. Apps folgen keinen Änderungen.", ), ("pim_location", "Ort"), ("pim_manage", "Einstellungen"), ("pim_manage_of", "Einstellungen für {}"), ("pim_members", "Mitglieder"), ("pim_mode_ro", "Nur lesen"), ("pim_mode_rw", "Lesen und schreiben"), ( "pim_mode_schedule", "Lesen, schreiben und Einladungen senden", ), ("pim_month", "Monat"), ("pim_more_n", "+{} weitere"), ("pim_name_from_file", "Aus der Datei, wenn leer"), ("pim_nav", "Kalender & Kontakte"), ("pim_new_address_book", "Neues Adressbuch"), ("pim_new_book_from_file", "Neues Adressbuch aus Datei"), ("pim_new_calendar", "Neuer Kalender"), ("pim_new_calendar_from_file", "Neuer Kalender aus Datei"), ("pim_new_from_file", "Neu aus Datei…"), ("pim_new_room", "Neuer Raum"), ("pim_next_month", "Nächster Monat"), ( "pim_no_contacts", "Noch keine Kontakte. Fügen Sie welche mit einer Kontakte-App oder einem Import hinzu.", ), ( "pim_no_events_agenda", "Keine Termine in den nächsten 7 Tagen.", ), ("pim_no_events_day", "Keine Termine an diesem Tag."), ("pim_no_feeds", "Keine öffentlichen Feeds."), ("pim_no_invitations", "Keine offenen Einladungen."), ("pim_no_links", "Keine öffentlichen Links."), ("pim_no_match", "Kein Kontakt passt."), ("pim_no_rooms", "Keine Räume oder Ressourcen."), ("pim_no_shares", "Mit niemandem geteilt."), ("pim_no_title", "(ohne Titel)"), ("pim_not_contact", "Dieser Eintrag ist kein Kontakt."), ("pim_not_event", "Dieser Eintrag ist kein Termin."), ("pim_note", "Notiz"), ("pim_optional", "optional"), ("pim_organizer", "Organisator"), ( "pim_password_hint", "Nutzen Sie ein App-Passwort statt Ihres Kontopassworts.", ), ("pim_phone", "Telefon"), ( "pim_pick_contact", "Wählen Sie einen Kontakt, um die Details zu sehen.", ), ("pim_postal", "Adresse"), ("pim_prev_month", "Vorheriger Monat"), ("pim_ps_accepted", "Zugesagt"), ("pim_ps_declined", "Abgesagt"), ("pim_ps_delegated", "Delegiert"), ("pim_ps_needs_action", "Noch keine Antwort"), ("pim_ps_tentative", "Vielleicht"), ("pim_remove_from_list", "Aus meiner Liste entfernen"), ( "pim_remove_msg", "Sie sehen ihn nicht mehr. Der Eigentümer kann ihn erneut teilen.", ), ("pim_removed", "Aus Ihrer Liste entfernt"), ("pim_repeats", "Wiederholung"), ("pim_replied", "Antwort gesendet"), ( "pim_room_delete_confirm", "„{}“ löschen? Seine Buchungen gehen verloren.", ), ("pim_room_display", "Anzeigename"), ("pim_room_name", "Name (Teil der Adresse, nicht änderbar)"), ("pim_rooms", "Räume und Ressourcen"), ( "pim_rooms_hint", "Räume und Ressourcen können zu Terminen eingeladen werden. Sie nehmen freie Zeiten an und lehnen belegte selbst ab.", ), ("pim_rrule_daily", "Jeden Tag"), ("pim_rrule_daily_n", "Alle {} Tage"), ("pim_rrule_monthly", "Jeden Monat"), ("pim_rrule_monthly_n", "Alle {} Monate"), ("pim_rrule_weekly", "Jede Woche"), ("pim_rrule_weekly_n", "Alle {} Wochen"), ("pim_rrule_yearly", "Jedes Jahr"), ("pim_rrule_yearly_n", "Alle {} Jahre"), ("pim_save_err", "Speichern fehlgeschlagen: {}"), ("pim_search_contacts", "Kontakte suchen"), ("pim_server_address", "Serveradresse"), ( "pim_server_address_hint", "Wenn eine App den Server nicht findet, nutzen Sie diese Adresse:", ), ("pim_shared_by", "Geteilt von {}"), ("pim_shared_ok", "Geteilt mit {}"), ("pim_shared_with_me", "Mit mir geteilt"), ("pim_sharing", "Teilen"), ( "pim_sharing_hint", "Mit einem anderen Konto auf diesem Server teilen.", ), ("pim_show", "Einblenden"), ("pim_show_all", "Alle anzeigen"), ("pim_show_only", "Nur diesen Eintrag anzeigen"), ( "pim_skip_component", "dieser Typ wird hier nicht angenommen", ), ("pim_skip_invalid", "ungültige oder unvollständige Daten"), ("pim_skip_size", "zu groß"), ( "pim_skip_uid", "dieselbe UID liegt schon in einem anderen Kalender", ), ("pim_subscribe", "Abonnieren"), ("pim_tentative", "Vielleicht"), ("pim_this_event", "Nur dieser Termin"), ("pim_today", "Heute"), ( "pim_transparent", "Als frei anzeigen: Termine blockieren bei Einladungen keine Zeitfenster", ), ( "pim_truncated", "Nicht alle Termine passen in diese Ansicht. Blenden Sie Kalender aus, um den Rest zu sehen.", ), ("pim_unshare", "Nicht mehr teilen"), ("pim_unshared", "Nicht mehr geteilt"), ("pim_until_time", "bis {}"), ("pim_upcoming", "Nächste 7 Tage"), ("pim_user", "Benutzername"), ("pim_user_name", "Benutzername"), ("pim_website", "Webseite"), ("pim_when", "Wann"), ("pim_your_answer", "Ihre Antwort"), ("profile", "Profil"), ( "profile_save_err", "Profil konnte nicht gespeichert werden: {}", ), ("profile_saved", "Profil gespeichert"), ( "pw_short", "Das Passwort muss mindestens 8 Zeichen lang sein.", ), ("read_only_badge", "Schreibgeschützt"), ("read_only_hint", "Schreibgeschützter Ordner"), ("refresh", "Aktualisieren"), ("refresh_folders", "Ordner aktualisieren"), ("remove_folder", "Ordner entfernen"), ("remove_password", "Passwort entfernen"), ( "remove_password_desc", "Nur noch mit Passkeys anmelden. Braucht mindestens einen Passkey.", ), ("rename", "Umbenennen"), ("rename_title", "„{}“ umbenennen"), ("renamed", "Umbenannt"), ("repeat_password", "Passwort wiederholen"), ("retry", "Erneut versuchen"), ("root_dup_err", "Dieser Ordner ist bereits in der Liste."), ( "rw_disabled", "Schreibbare Freigaben sind vom Server deaktiviert.", ), ( "rw_ro_folder", "Dieser Ordner ist schreibgeschützt, daher ist die Freigabe auch schreibgeschützt.", ), ("save", "Speichern"), ("save_profile", "Profil speichern"), ("save_settings", "Einstellungen speichern"), ("saved", "Gespeichert"), ("saving", "Wird gespeichert…"), ("search", "Suche"), ("search_both", "Beides"), ("search_collapse_all", "Alle einklappen"), ("search_content", "Inhalt"), ("search_excludes", "Von der Suche ausgeschlossen"), ("search_excludes_empty", "Keine Ordner ausgeschlossen."), ("search_expand_all", "Alle ausklappen"), ("search_failed", "Die Suche ist fehlgeschlagen."), ("search_goto", "Im Ordner anzeigen"), ("search_here", "Hier suchen"), ("search_in", "Suchen in…"), ("search_in_folder", "In diesem Ordner suchen"), ("search_in_n_files", "in {} Dateien"), ("search_n_matches", "{} Treffer"), ("search_n_results", "{} Treffer"), ("search_name", "Name"), ("search_no_results", "keine Treffer"), ( "search_placeholder", "Dateien und deren Inhalte durchsuchen", ), ("search_run", "Suchen"), ("search_scanned", "{} Dateien durchsucht"), ("search_show_more", "{} weitere anzeigen"), ("search_shown_of", "{} von {} angezeigt"), ("search_skipped", "{} übersprungen (über 10 MiB)"), ("search_stop", "Stopp"), ("search_stopped", "gestoppt · {} Treffer"), ("search_took", "{} ms"), ("searching", "Suche läuft…"), ( "second_factor_passkey", "Bestätigen Sie jetzt mit Ihrem Passkey.", ), ("second_factor_password", "Passwort für {} eingeben."), ("security", "Sicherheit"), ( "select_folder_msg", "Wählen Sie links einen Ordner aus, um mit dem Durchsuchen zu beginnen.", ), ("select_folder_title", "Ordner auswählen"), ("server", "Server"), ("server_root", "Serverwurzel"), ("server_unreachable", "Der Server ist nicht erreichbar."), ("settings", "Einstellungen"), ( "settings_save_err", "Einstellungen konnten nicht gespeichert werden: {}", ), ("settings_saved", "Einstellungen gespeichert"), ( "setup_intro", "Erster Start: Erstellen Sie das Administrator-Konto. Dieser Benutzer kann andere Benutzer und die Servereinstellungen verwalten.", ), ("setup_pw_mismatch", "Die Passwörter stimmen nicht überein."), ("share", "Teilen"), ( "share_create_err", "Freigabe konnte nicht erstellt werden: {}", ), ("share_delete_err", "Freigabe konnte nicht gelöscht werden"), ("share_deleted", "Freigabe gelöscht"), ( "share_dialog_hint", "Erstellt einen Link für diesen Eintrag. Mit schreibbaren Links können Empfänger Dateien hochladen und bearbeiten.", ), ("share_expired", "Freigabe abgelaufen"), ( "share_expired_msg", "Dieser Freigabelink ist nicht mehr aktiv.", ), ("share_link", "Freigabelink"), ("share_locked_title", "Passwort erforderlich"), ("share_not_found", "Freigabe nicht gefunden"), ( "share_not_found_msg", "Dieser Link ist ungültig oder die Freigabe wurde entfernt.", ), ("share_owner_disabled", "deaktiviertes Konto"), ( "share_password_hint", "Optional. Besucher müssen es eingeben, bevor die Freigabe geöffnet wird, mindestens 8 Zeichen.", ), ("share_perm_ro", "Jeder mit diesem Link kann „{}“ lesen."), ( "share_perm_rw", "Jeder mit diesem Link kann „{}“ lesen und schreiben.", ), ("share_protected", "Passwortgeschützt"), ("share_title", "{} teilen"), ("shares", "Freigaben"), ( "shares_delete_err", "Freigaben konnten nicht gelöscht werden", ), ( "shares_empty_hint", "Klicken Sie mit der rechten Maustaste auf eine Datei oder einen Ordner und wählen Sie „Teilen“, um einen Link zu erstellen.", ), ( "shares_view_hint", "Von Ihnen erstellte Links. Klicken Sie mit der rechten Maustaste auf eine Datei oder einen Ordner und wählen Sie „Teilen“, um einen hinzuzufügen.", ), ("sign_in", "Anmelden"), ("signin_both", "Passwort und Passkey"), ( "signin_both_desc", "Beides ist nötig. WebDAV braucht dann ein App-Passwort, weil eine Einbindung nur ein Passwort senden kann.", ), ("signin_either", "Passwort oder Passkey"), ( "signin_either_desc", "Eines davon allein genügt zur Anmeldung.", ), ("signin_requirement", "Anmeldung verlangt"), ( "single_click_desc", "Wenn aktiv, öffnet ein einfacher Klick einen Eintrag und Strg+Klick wählt ihn aus. Wenn inaktiv, wählt ein einfacher Klick aus und ein Doppelklick öffnet.", ), ("single_click_label", "Einzelklick öffnet Einträge"), ("size", "Größe"), ("some_files_exist", "Einige Dateien existieren bereits"), ("sort_asc", "Aufsteigend"), ("sort_by", "Sortieren nach"), ("sort_desc", "Absteigend"), ("theme_auto", "Auto"), ("theme_dark", "Dunkel"), ("theme_light", "Hell"), ("theme_title", "Design: {} (klicken zum Wechseln)"), ( "thumbnails_desc", "Für Bilder und Videos in der Kachelansicht eine kleine Vorschau statt eines Symbols zeigen.", ), ("thumbnails_label", "Vorschaubilder zeigen"), ("type", "Typ"), ("unlock", "Freigabe öffnen"), ("unsaved_changes", "Ungespeicherte Änderungen"), ("until", "Bis"), ("upload_abort", "Abbrechen"), ("upload_aborted", "Abgebrochen"), ("upload_active_n", "{} aktiv"), ( "upload_apply_all", "Auch auf Dateien anwenden, die während des Uploads entstehen", ), ( "upload_check_failed", "Prüfung auf vorhandene Dateien fehlgeschlagen: {}", ), ("upload_clear", "Aus der Liste entfernen"), ("upload_clear_finished", "Abgeschlossene entfernen"), ("upload_collapse", "Einklappen"), ("upload_complete", "Hochladen abgeschlossen"), ( "upload_conflict_question", "Die folgenden Dateien existieren bereits. Überschreiben oder überspringen?", ), ("upload_drop_hint", "Zum Hochladen hier ablegen"), ("upload_errors_n", "{} fehlgeschlagen"), ( "upload_exists_ask", "„{}“ ist während des Uploads auf dem Server entstanden.", ), ("upload_expand", "Ausklappen"), ("upload_failed", "Fehlgeschlagen"), ("upload_files", "Dateien hochladen"), ("upload_folder", "Ordner hochladen"), ("upload_n_files", "{} Dateien"), ("upload_pause", "Pausieren"), ("upload_paused", "Pausiert"), ("upload_preparing", "Wird vorbereitet…"), ("upload_resume", "Fortsetzen"), ("upload_show_graph", "Details und Geschwindigkeitsverlauf"), ("upload_skip", "Überspringen"), ("upload_skipped_n", "{} übersprungen"), ("upload_speed", "{}/s"), ("upload_waiting", "Wartet auf Ihre Antwort"), ("uploads", "Uploads"), ("uploads_empty", "Noch keine Uploads"), ("use_passkey", "Passkey verwenden"), ( "use_passkey_hint", "Lassen Sie den Namen leer, außer Ihr Passkey braucht ihn.", ), ("user_created", "Benutzer erstellt"), ("user_delete_err", "Benutzer konnte nicht gelöscht werden"), ("user_disabled", "deaktiviert"), ("user_name_example", "z. B. alice"), ( "user_save_err", "Benutzer konnte nicht gespeichert werden: {}", ), ("user_updated", "Benutzer aktualisiert"), ("user_you", "(Sie)"), ("users", "Benutzer"), ("week_monday", "Montag"), ("week_saturday", "Samstag"), ("week_start", "Woche beginnt am"), ("week_start_desc", "Der erste Wochentag im Kalender."), ("week_sunday", "Sonntag"), ("your_shares", "Ihre Freigaben"), ]; /// French translations. const FR: &[(&str, &str)] = &[ ("active_can_signin", "Actif (peut se connecter)"), ("add_app_password", "Créer un mot de passe d'application"), ("add_folder", "Ajouter un dossier…"), ("add_here", "Ajouter ce dossier"), ("add_passkey", "Ajouter une clé d'accès"), ("administrator", "Administrateur"), ("all_shares", "Tous les partages"), ( "all_shares_hint", "Tous les liens de ce serveur, groupés par le compte qui les a créés.", ), ( "allow_editing", "Autoriser la modification (lecture-écriture)", ), ("allow_rw_shares", "Autoriser les partages modifiables"), ( "allow_rw_shares_desc", "Autoriser les utilisateurs à créer des liens de partage en lecture-écriture. Désactivé par défaut.", ), ("and_more", "…et {} autres"), ("app_password_label", "Nom de ce mot de passe d'application"), ("app_password_removed", "Mot de passe d'application révoqué"), ( "app_password_secret_once", "Copiez-le maintenant. Il ne sera plus jamais affiché.", ), ("app_passwords", "Mots de passe d'application"), ( "app_passwords_hint", "Un mot de passe d'application ne sert qu'au WebDAV, jamais à cette page. Utilisez-en un par client au lieu de votre mot de passe de compte.", ), ("cancel", "Annuler"), ( "cant_delete_self", "Vous ne pouvez pas supprimer votre propre compte", ), ("close", "Fermer"), ("close_esc", "Fermer (Échap)"), ("copied", "Copié"), ("copy", "Copier"), ("copy_dav_link", "Copier le lien WebDAV"), ("copy_here", "Copier ici"), ("copy_link", "Copier le lien"), ("copy_manual", "Copiez le lien manuellement"), ("copy_n_to", "Copier {} éléments vers…"), ("copy_to", "Copier « {} » vers…"), ("create", "Créer"), ("create_admin", "Créer le compte administrateur"), ("create_link", "Créer le lien"), ("create_user", "Créer l'utilisateur"), ("creating", "Création…"), ("ct_type_cell", "portable"), ("ct_type_fax", "fax"), ("ct_type_home", "domicile"), ("ct_type_other", "autre"), ("ct_type_work", "travail"), ("custom", "Personnalisé…"), ( "default_root_desc", "Ouvrir ce dossier au chargement de la page et via le lien d'accueil.", ), ("default_root_label", "Dossier par défaut"), ("default_root_none", "Aperçu des dossiers"), ("delete", "Supprimer"), ("delete_all", "Tout supprimer"), ( "delete_all_msg", "Supprimer les {} liens de partage ? Toute personne les possédant perdra l'accès. Cette action est irréversible.", ), ("delete_all_title", "Supprimer tous les partages ?"), ( "delete_all_user_msg", "Supprimer tous les liens de partage de « {} » ? Toute personne les possédant perdra l'accès. Cette action est irréversible.", ), ( "delete_folder_msg", "Supprimer le dossier « {} » et tout son contenu ?\nCette action est irréversible.", ), ( "delete_msg", "Supprimer « {} » ?\nCette action est irréversible.", ), ( "delete_n_msg", "Supprimer {} éléments ?\nCette action est irréversible.", ), ( "delete_partial", "{} des {} liens n'ont pas pu être supprimés", ), ("delete_share", "Supprimer le partage"), ("delete_user", "Supprimer l'utilisateur"), ( "delete_user_confirm", "Supprimer l'utilisateur « {} » ? Cette action est irréversible.", ), ("deleted", "Supprimé"), ("deleted_n_shares", "{} partage(s) supprimé(s)"), ("discard", "Abandonner"), ( "discard_question", "Abandonner vos modifications et fermer l'éditeur ?", ), ("dismiss", "Ignorer"), ("dismiss_error", "Ignorer l'erreur"), ("done", "Terminé"), ("download", "Télécharger"), ( "download_formats_msg", "Choisissez un format d'archivage pour le dossier.", ), ("download_started", "Téléchargement démarré"), ("download_title", "Télécharger « {} »"), ("edit", "Modifier"), ("edit_user_title", "Modifier « {} »"), ("empty_folder", "Ce dossier est vide."), (k::ERR_ADMIN_ONLY, "réservé aux administrateurs"), (k::ERR_ALREADY_SET_UP, "le serveur est déjà configuré"), ( k::ERR_APP_PASSWORD_LIMIT, "Ce compte possède déjà le nombre maximal de mots de passe d'application.", ), ( k::ERR_APP_PASSWORD_NOT_FOUND, "Aucun mot de passe d'application correspondant.", ), (k::ERR_BAD_ACTION, "action=content attendu"), (k::ERR_BAD_BODY, "corps de requête invalide"), (k::ERR_BAD_EXPIRES_AT, "la date d'expiration est invalide"), ( k::ERR_BAD_FORMAT, "le format doit être zip, tar, tar.gz ou tar.zst", ), ( k::ERR_BAD_MULTIPART, "multipart/form-data avec boundary attendu", ), (k::ERR_BAD_PART_NAME, "nom de partie invalide"), ( k::ERR_BAD_POST, "POST attend un téléversement multipart, une mutation JSON ou ?action=mkdir/create-file", ), (k::ERR_BAD_UPLOAD, "données de téléversement invalides"), ( k::ERR_BAD_UPLOAD_PATH, "chemin de fichier invalide dans le téléversement", ), ( k::ERR_CHALLENGE_EXPIRED, "Cela a pris trop de temps. Veuillez réessayer.", ), ( k::ERR_DEFAULT_CALENDAR, "Le calendrier qui reçoit les invitations ne peut pas être supprimé.", ), (k::ERR_DST_REQUIRED, "dst_root_id est requis"), (k::ERR_FILE_NAME_REQUIRED, "un nom de fichier est requis"), (k::ERR_FILES_EXIST, "certains fichiers existent déjà"), (k::ERR_FOLDER_EXISTS, "un dossier avec ce nom existe déjà"), (k::ERR_FOLDER_NAME_REQUIRED, "un nom de dossier est requis"), (k::ERR_FS_CONFLICT, "existe déjà"), (k::ERR_FS_FORBIDDEN, "accès refusé"), (k::ERR_FS_NOT_A_DIR, "ce n'est pas un dossier"), (k::ERR_FS_NOT_FOUND, "dossier introuvable"), (k::ERR_FS_ROOT_MISSING, "le dossier configuré n'existe plus"), (k::ERR_INTERNAL, "erreur interne"), (k::ERR_INVALID_CREDENTIALS, "nom ou mot de passe incorrect"), ( k::ERR_INVALID_DEFAULT_ROOT, "le dossier par défaut ne fait pas partie de vos dossiers", ), (k::ERR_INVALID_LANGUAGE, "balise de langue invalide"), (k::ERR_INVALID_WEEK_START, "début de semaine invalide"), ( k::ERR_LAST_ADMIN, "impossible de supprimer le dernier administrateur actif", ), ( k::ERR_LAST_ADMIN_DELETE, "impossible de supprimer le dernier administrateur actif", ), ( k::ERR_LOCKED_OUT, "Le compte n'aurait alors plus aucun moyen de connexion.", ), ( k::ERR_MODE_NEEDS_PASSKEY, "Ajoutez une clé d'accès avant d'exiger les deux.", ), ( k::ERR_MODE_NEEDS_PASSWORD, "Définissez un mot de passe avant d'exiger les deux.", ), (k::ERR_NAME_LENGTH, "le nom doit contenir 1 à 64 caractères"), (k::ERR_NEW_NAME_REQUIRED, "new_name est requis"), (k::ERR_NO_FILES_UPLOADED, "aucun fichier n'a été téléversé"), (k::ERR_NO_SUCH_FOLDER, "ce dossier n'existe pas"), (k::ERR_NOT_A_FILE, "ce n'est pas un fichier"), (k::ERR_NOT_SIGNED_IN, "non connecté"), ( k::ERR_OWN_ACCOUNT, "vous ne pouvez pas désactiver votre propre compte", ), ( k::ERR_OWN_ADMIN, "vous ne pouvez pas retirer vos propres droits d'administrateur", ), ( k::ERR_OWN_DELETE, "vous ne pouvez pas supprimer votre propre compte", ), (k::ERR_PART_NO_NAME, "partie sans nom"), ( k::ERR_PASSKEY_DUPLICATE, "Cette clé d'accès est déjà enregistrée.", ), ( k::ERR_PASSKEY_FAILED, "Cette clé d'accès n'a pas pu être utilisée.", ), ( k::ERR_PASSKEY_LAST_CREDENTIAL, "Définissez un mot de passe avant de retirer votre dernière clé d'accès.", ), ( k::ERR_PASSKEY_LIMIT, "Ce compte a déjà autant de clés d'accès que permis.", ), ( k::ERR_PASSKEY_MALFORMED, "Le navigateur a envoyé des données illisibles.", ), (k::ERR_PASSKEY_NOT_FOUND, "Clé d'accès introuvable."), ( k::ERR_PASSKEY_ORIGIN, "Les clés d'accès sont configurées pour une autre adresse.", ), ( k::ERR_PASSKEY_UNAVAILABLE, "Les clés d'accès ne sont pas disponibles ici.", ), ( k::ERR_PASSWORD_LAST_CREDENTIAL, "Ajoutez une clé d'accès avant de retirer votre mot de passe.", ), ( k::ERR_PASSWORD_SHORT, "le mot de passe doit contenir au moins 8 caractères", ), (k::ERR_PATH_REQUIRED, "un chemin dans le dossier est requis"), (k::ERR_READ_ONLY_FOLDER, "dossier en lecture seule"), ( k::ERR_REQUIRED_BY_MODE, "Ce compte exige un mot de passe et une clé d'accès.", ), (k::ERR_ROOT_FORBIDDEN, "dossier inaccessible"), ( k::ERR_RW_RO_FOLDER, "ce dossier est en lecture seule pour vous, il ne peut donc pas être partagé en écriture", ), ( k::ERR_RW_SHARES_DISABLED, "les partages modifiables sont désactivés", ), (k::ERR_SAVE_FAILED, "impossible d'enregistrer le fichier"), ( k::ERR_SEARCH_BAD_SCOPE, "la portée doit être name, content ou both", ), ( k::ERR_SEARCH_FORBIDDEN, "la recherche nécessite une session connectée", ), ( k::ERR_SESSION_EXPIRED, "session expirée, veuillez vous connecter à nouveau", ), (k::ERR_SHARE_EXPIRED, "ce partage a expiré"), ( k::ERR_SHARE_LOCKED, "Ce partage est protégé par un mot de passe.", ), ( k::ERR_SHARE_NO_PASSWORD, "Ce partage n'a pas de mot de passe.", ), (k::ERR_SHARE_NOT_FOUND, "partage introuvable"), ( k::ERR_SHARE_TOKEN_FORBIDDEN, "un jeton de partage ne peut pas être utilisé ici ; connectez-vous à la place", ), (k::ERR_SHARE_WRONG_PASSWORD, "Mot de passe incorrect."), ( k::ERR_TOO_LARGE_PREVIEW, "fichier trop volumineux pour l'aperçu", ), ( k::ERR_TOO_LARGE_SAVE, "fichier trop volumineux pour être enregistré", ), (k::ERR_USER_EXISTS, "un utilisateur avec ce nom existe déjà"), (k::ERR_USER_NOT_FOUND, "utilisateur introuvable"), ("exclude_dup_err", "Ce dossier est déjà exclu."), ("exclude_folder", "Exclure un dossier…"), ("exclude_here", "Exclure ce dossier"), ( "exclude_root_err", "La racine entière ne peut pas être exclue ; cela désactiverait la recherche.", ), ("expires", "Expire"), ("expires_at", "Expire le {}"), ("expiry_1d", "1 jour"), ("expiry_1h", "1 heure"), ("expiry_1mo", "1 mois"), ("expiry_1w", "1 semaine"), ("file", "Fichier"), ("file_changed", "Fichier modifié sur disque"), ("file_created", "Fichier créé"), ("file_info", "Informations"), ("file_name", "Nom du fichier"), ("file_not_found", "Fichier introuvable"), ("files", "Fichiers"), ("fmt_tar", "Tar"), ("fmt_targz", "Tar + gzip"), ("fmt_tarzst", "Tar + zstd"), ("fmt_zip", "Zip"), ("folder", "Dossier"), ("folder_created", "Dossier créé"), ( "folder_gone_msg", "Ce dossier n'est plus accessible. Choisissez-en un autre dans le panneau latéral.", ), ("folder_gone_title", "Dossier indisponible"), ("folder_name", "Nom du dossier"), ("folders", "Dossiers"), ( "folders_paths_hint", "Les chemins sont relatifs à la racine du serveur. « . » désigne toute la racine.", ), ("grid_view", "Vue en grille"), ("info", "Infos"), ("keep_editing", "Continuer à modifier"), ("lang_auto", "Automatique"), ("lang_de", "Allemand"), ("lang_en", "Anglais"), ("lang_fr", "Français"), ("language", "Langue"), ( "language_desc", "La langue de l'interface. « Automatique » utilise la langue de votre navigateur.", ), ("link_copied", "Lien copié dans le presse-papiers"), ("list_view", "Vue en liste"), ("load_latest", "Charger la version la plus récente"), ("loading", "Chargement…"), ("loading_share", "Chargement du partage…"), ("location", "Emplacement"), ("log_out", "Se déconnecter"), ("login_subtitle", "Connectez-vous pour continuer."), ("manage", "Gérer"), ("menu", "Menu"), ("meta_created", "créé le {}"), ("meta_expires", "expire le {}"), ("mode_ro", "lecture seule"), ("mode_rw", "lecture-écriture"), ("modified", "Modifié"), ( "modified_after", "Ce fichier a été modifié après son ouverture. « Charger la version la plus récente » abandonne vos modifications non enregistrées ; « Écraser » conserve votre version.", ), ("more_actions", "Plus d'actions"), ("move", "Déplacer"), ("move_here", "Déplacer ici"), ("move_n_to", "Déplacer {} éléments vers…"), ("move_to", "Déplacer « {} » vers…"), ("moved", "Déplacé"), ("name", "Nom"), ("name_taken", "Ce nom est déjà utilisé"), ("need_folder", "Donnez au moins un dossier à l'utilisateur."), ("never", "Jamais"), ("never_expires", "N'expire jamais"), ("new_file", "Nouveau fichier"), ("new_folder", "Nouveau dossier"), ("new_name", "Nouveau nom"), ("new_password", "Nouveau mot de passe"), ( "new_password_hint", "Laissez vide pour conserver votre mot de passe actuel.", ), ( "new_password_keep", "Nouveau mot de passe (laisser vide pour conserver)", ), ("new_user", "Nouvel utilisateur"), ("no_app_passwords", "Aucun mot de passe d'application."), ( "no_folders_msg", "Aucun administrateur ne vous a encore attribué de dossier.", ), ("no_folders_title", "Aucun dossier disponible"), ("no_passkeys", "Aucune clé d'accès pour l'instant."), ( "no_password_set", "Ce compte se connecte uniquement avec des clés d'accès.", ), ("no_preview", "Aperçu non disponible"), ( "no_preview_msg", "L'application ne peut pas afficher « {} » ici.", ), ("no_shares", "Aucun partage pour l'instant"), ("no_subfolders", "Aucun sous-dossier"), ("no_users", "Aucun utilisateur."), ("open", "Ouvrir"), ("open_in_new_tab", "Ouvrir dans un nouvel onglet"), ("open_menu", "Ouvrir le menu"), ("or_label", "ou"), ("overwrite", "Écraser"), ( "overwrite_question", "Les fichiers suivants existent déjà. Les écraser ?", ), ("page_first", "Première page"), ("page_goto", "Page"), ("page_last", "Dernière page"), ("page_next", "Page suivante"), ("page_prev", "Page précédente"), ("page_size", "Entrées par page"), ("page_size_n", "{} par page"), ("passkey_added", "Clé d'accès ajoutée"), ("passkey_added_on", "Ajoutée {}"), ("passkey_label", "Nom de cette clé d'accès"), ("passkey_last_used", "Dernière utilisation {}"), ("passkey_needs_name", "Exige votre nom d'utilisateur"), ( "passkey_needs_name_hint", "Cette clé d'accès n'est pas stockée dans l'authentificateur, le serveur doit la retrouver. Saisissez votre nom d'utilisateur sur la page de connexion avant de l'utiliser.", ), ("passkey_never_used", "Jamais utilisée"), ("passkey_not_used", "Aucune clé d'accès n'a été utilisée."), ("passkey_removed", "Clé d'accès retirée"), ( "passkey_unsupported", "Ce navigateur ne peut pas utiliser de clés d'accès.", ), ("passkeys", "Clés d'accès"), ( "passkeys_hint", "Une clé d'accès vous connecte avec votre empreinte, votre visage ou une clé de sécurité.", ), ("password", "Mot de passe"), ("password_min_hint", "au moins 8 caractères"), ("password_removed", "Mot de passe retiré"), ( "password_resets_signin", "Définir un mot de passe supprime aussi les clés d'accès de ce compte et lève toute exigence à deux facteurs.", ), ("pim_accept", "Accepter"), ("pim_access", "Accès"), ("pim_add", "Ajouter"), ("pim_address", "Adresse pour les applications"), ("pim_address_book", "Carnet d'adresses"), ("pim_address_books", "Carnets d'adresses"), ("pim_agenda", "Agenda"), ("pim_all_day", "Toute la journée"), ("pim_all_events", "Tous les événements de la série"), ("pim_anniversary", "Anniversaire de mariage"), ("pim_app_passwords", "Créer un mot de passe d'application"), ("pim_attendees", "Participants"), ("pim_auto", "automatique"), ("pim_back", "Retour"), ("pim_birthday", "Anniversaire"), ("pim_birthdays", "Anniversaires"), ("pim_calendar", "Calendrier"), ("pim_calendars", "Calendriers"), ("pim_cancelled", "Annulé"), ("pim_categories", "Catégories"), ("pim_clients", "Applications"), ( "pim_collection_urls", "Adresses des calendriers et carnets d'adresses", ), ("pim_color", "Couleur"), ("pim_connect", "Connecter une application"), ( "pim_connect_title", "Connecter une application de calendrier ou de contacts", ), ("pim_contacts", "Contacts"), ("pim_created", "Créé"), ("pim_custom_color", "Couleur personnalisée"), ("pim_decline", "Refuser"), ( "pim_default_hint", "Ce calendrier reçoit les invitations. Il ne peut pas être supprimé.", ), ( "pim_delete_msg", "Tout son contenu est supprimé. Les participants à vos réunions reçoivent une annulation.", ), ("pim_delete_title", "Supprimer « {} » ?"), ("pim_description", "Description"), ("pim_detail", "Détails"), ("pim_detail_busy", "Heures occupées seulement"), ("pim_detail_full", "Tous les détails"), ("pim_directory", "Annuaire"), ("pim_email", "E-mail"), ("pim_export", "Exporter"), ("pim_feeds", "Flux de calendriers et de contacts"), ( "pim_feeds_hint", "Chaque lien public de calendrier et de carnet d'adresses sur ce serveur.", ), ("pim_file", "Fichier"), ("pim_from_organizer", "De {}"), ("pim_from_time", "à partir de {}"), ("pim_general", "Général"), ( "pim_generated_hint", "Le serveur le remplit. Il est en lecture seule.", ), ("pim_group", "Groupe"), ("pim_hide", "Masquer"), ( "pim_hint_apple", "Apple : ajoutez un compte CalDAV et un compte CardDAV avec l'adresse du serveur. Apple exige HTTPS.", ), ( "pim_hint_davx5", "Android : dans DAVx⁵, connectez-vous avec URL et nom d'utilisateur, et utilisez l'adresse du serveur.", ), ( "pim_hint_gnome", "GNOME et Evolution : ajoutez un compte CalDAV ou WebDAV avec l'adresse du serveur.", ), ( "pim_hint_thunderbird", "Thunderbird : ajoutez un calendrier réseau avec l'adresse du serveur. Réglez son identité e-mail sur « Aucune », sinon il n'envoie pas d'invitations.", ), ("pim_import", "Importer"), ("pim_import_done", "{} nouveaux, {} mis à jour."), ("pim_import_file", "Importer un fichier…"), ( "pim_import_hint_cal", "Ajoute les événements d'un fichier .ics à ce calendrier. Un événement déjà présent est mis à jour.", ), ( "pim_import_hint_cards", "Ajoute les contacts d'un fichier .vcf à ce carnet d'adresses. Un contact déjà présent est mis à jour.", ), ( "pim_import_new_hint_cal", "Crée un agenda avec les événements d'un fichier .ics.", ), ( "pim_import_new_hint_cards", "Crée un carnet d'adresses avec les contacts d'un fichier .vcf.", ), ( "pim_import_nothing", "Rien n'a pu être importé, donc rien n'a été créé.", ), ("pim_import_skipped", "{} ignorés :"), ("pim_imported_as", "Importé sous « {} »."), ("pim_importing", "Importation…"), ( "pim_inv_series_hint", "Votre réponse vaut pour toute la série.", ), ("pim_invitations", "Invitations"), ("pim_kind_resource", "Ressource"), ("pim_kind_room", "Salle"), ("pim_link", "Lien"), ("pim_link_busy", "heures occupées seulement"), ("pim_link_full", "tous les détails"), ("pim_link_revoked", "Lien révoqué"), ("pim_links", "Liens publics"), ( "pim_links_hint", "Toute personne ayant le lien peut s'abonner. Certains agendas, comme Google Agenda et Outlook.com, exigent un lien sans mot de passe.", ), ( "pim_links_hint_cards", "Toute personne ayant le lien peut télécharger les contacts une fois. Les applications ne suivent pas les modifications.", ), ("pim_location", "Lieu"), ("pim_manage", "Paramètres"), ("pim_manage_of", "Paramètres de {}"), ("pim_members", "Membres"), ("pim_mode_ro", "Lecture seule"), ("pim_mode_rw", "Lecture et écriture"), ( "pim_mode_schedule", "Lecture, écriture et envoi d'invitations", ), ("pim_month", "Mois"), ("pim_more_n", "+{} autres"), ("pim_name_from_file", "Tiré du fichier si vide"), ("pim_nav", "Calendrier et contacts"), ("pim_new_address_book", "Nouveau carnet d'adresses"), ( "pim_new_book_from_file", "Nouveau carnet d'adresses depuis un fichier", ), ("pim_new_calendar", "Nouveau calendrier"), ( "pim_new_calendar_from_file", "Nouvel agenda depuis un fichier", ), ("pim_new_from_file", "Nouveau depuis un fichier…"), ("pim_new_room", "Nouvelle salle"), ("pim_next_month", "Mois suivant"), ( "pim_no_contacts", "Pas encore de contacts. Ajoutez-en avec une application de contacts ou une importation.", ), ( "pim_no_events_agenda", "Aucun événement dans les 7 prochains jours.", ), ("pim_no_events_day", "Aucun événement ce jour-là."), ("pim_no_feeds", "Aucun flux public."), ("pim_no_invitations", "Aucune invitation en attente."), ("pim_no_links", "Aucun lien public."), ("pim_no_match", "Aucun contact ne correspond."), ("pim_no_rooms", "Aucune salle ni ressource."), ("pim_no_shares", "Partagé avec personne."), ("pim_no_title", "(sans titre)"), ("pim_not_contact", "Cette entrée n'est pas un contact."), ("pim_not_event", "Cette entrée n'est pas un événement."), ("pim_note", "Note"), ("pim_optional", "facultatif"), ("pim_organizer", "Organisateur"), ( "pim_password_hint", "Utilisez un mot de passe d'application plutôt que celui de votre compte.", ), ("pim_phone", "Téléphone"), ( "pim_pick_contact", "Choisissez un contact pour voir les détails.", ), ("pim_postal", "Adresse"), ("pim_prev_month", "Mois précédent"), ("pim_ps_accepted", "Accepté"), ("pim_ps_declined", "Refusé"), ("pim_ps_delegated", "Délégué"), ("pim_ps_needs_action", "Pas encore de réponse"), ("pim_ps_tentative", "Peut-être"), ("pim_remove_from_list", "Retirer de ma liste"), ( "pim_remove_msg", "Vous ne le voyez plus. Le propriétaire peut le partager à nouveau.", ), ("pim_removed", "Retiré de votre liste"), ("pim_repeats", "Répétition"), ("pim_replied", "Réponse envoyée"), ( "pim_room_delete_confirm", "Supprimer « {} » ? Ses réservations sont perdues.", ), ("pim_room_display", "Nom affiché"), ( "pim_room_name", "Nom (fait partie de l'adresse, non modifiable)", ), ("pim_rooms", "Salles et ressources"), ( "pim_rooms_hint", "Les salles et ressources peuvent être invitées aux réunions. Elles acceptent les créneaux libres et refusent les occupés d'elles-mêmes.", ), ("pim_rrule_daily", "Tous les jours"), ("pim_rrule_daily_n", "Tous les {} jours"), ("pim_rrule_monthly", "Tous les mois"), ("pim_rrule_monthly_n", "Tous les {} mois"), ("pim_rrule_weekly", "Toutes les semaines"), ("pim_rrule_weekly_n", "Toutes les {} semaines"), ("pim_rrule_yearly", "Tous les ans"), ("pim_rrule_yearly_n", "Tous les {} ans"), ("pim_save_err", "Impossible d'enregistrer : {}"), ("pim_search_contacts", "Rechercher des contacts"), ("pim_server_address", "Adresse du serveur"), ( "pim_server_address_hint", "Si une application ne trouve pas le serveur, utilisez cette adresse :", ), ("pim_shared_by", "Partagé par {}"), ("pim_shared_ok", "Partagé avec {}"), ("pim_shared_with_me", "Partagés avec moi"), ("pim_sharing", "Partage"), ( "pim_sharing_hint", "Partager avec un autre compte de ce serveur.", ), ("pim_show", "Afficher"), ("pim_show_all", "Tout afficher"), ("pim_show_only", "Afficher seulement celui-ci"), ("pim_skip_component", "ce type n'est pas accepté ici"), ("pim_skip_invalid", "données invalides ou incomplètes"), ("pim_skip_size", "trop volumineux"), ( "pim_skip_uid", "le même UID existe déjà dans un autre calendrier", ), ("pim_subscribe", "S'abonner"), ("pim_tentative", "Peut-être"), ("pim_this_event", "Seulement cet événement"), ("pim_today", "Aujourd'hui"), ( "pim_transparent", "Afficher comme libre : les événements ne bloquent pas de créneaux dans les invitations", ), ( "pim_truncated", "Tous les événements ne tiennent pas dans cette vue. Masquez des calendriers pour voir le reste.", ), ("pim_unshare", "Ne plus partager"), ("pim_unshared", "N'est plus partagé"), ("pim_until_time", "jusqu'à {}"), ("pim_upcoming", "7 prochains jours"), ("pim_user", "Nom d'utilisateur"), ("pim_user_name", "Nom d'utilisateur"), ("pim_website", "Site web"), ("pim_when", "Quand"), ("pim_your_answer", "Votre réponse"), ("profile", "Profil"), ( "profile_save_err", "Impossible d'enregistrer le profil : {}", ), ("profile_saved", "Profil enregistré"), ( "pw_short", "Le mot de passe doit contenir au moins 8 caractères.", ), ("read_only_badge", "Lecture seule"), ("read_only_hint", "Dossier en lecture seule"), ("refresh", "Actualiser"), ("refresh_folders", "Actualiser vos dossiers"), ("remove_folder", "Retirer le dossier"), ("remove_password", "Retirer le mot de passe"), ( "remove_password_desc", "Se connecter uniquement avec des clés d'accès. Exige au moins une clé d'accès.", ), ("rename", "Renommer"), ("rename_title", "Renommer « {} »"), ("renamed", "Renommé"), ("repeat_password", "Répéter le mot de passe"), ("retry", "Réessayer"), ("root_dup_err", "Ce dossier est déjà dans la liste."), ( "rw_disabled", "Les partages modifiables sont désactivés par le serveur.", ), ( "rw_ro_folder", "Ce dossier est en lecture seule, le partage l'est donc aussi.", ), ("save", "Enregistrer"), ("save_profile", "Enregistrer le profil"), ("save_settings", "Enregistrer les paramètres"), ("saved", "Enregistré"), ("saving", "Enregistrement…"), ("search", "Rechercher"), ("search_both", "Les deux"), ("search_collapse_all", "Tout replier"), ("search_content", "Contenu"), ("search_excludes", "Exclu de la recherche"), ("search_excludes_empty", "Aucun dossier exclu."), ("search_expand_all", "Tout déplier"), ("search_failed", "La recherche a échoué."), ("search_goto", "Afficher dans le dossier"), ("search_here", "Rechercher ici"), ("search_in", "Rechercher dans…"), ("search_in_folder", "Rechercher dans ce dossier"), ("search_in_n_files", "dans {} fichiers"), ("search_n_matches", "{} correspondances"), ("search_n_results", "{} résultats"), ("search_name", "Nom"), ("search_no_results", "aucun résultat"), ( "search_placeholder", "Rechercher dans les fichiers et leur contenu", ), ("search_run", "Rechercher"), ("search_scanned", "{} fichiers parcourus"), ("search_show_more", "Afficher {} de plus"), ("search_shown_of", "{} sur {} affichés"), ("search_skipped", "{} ignorés (plus de 10 Mio)"), ("search_stop", "Arrêter"), ("search_stopped", "arrêté · {} résultats"), ("search_took", "{} ms"), ("searching", "recherche…"), ( "second_factor_passkey", "Confirmez maintenant avec votre clé d'accès.", ), ("second_factor_password", "Saisissez le mot de passe de {}."), ("security", "Sécurité"), ( "select_folder_msg", "Choisissez un dossier dans le panneau latéral pour commencer à naviguer.", ), ("select_folder_title", "Choisir un dossier"), ("server", "Serveur"), ("server_root", "Racine du serveur"), ("server_unreachable", "Le serveur est injoignable."), ("settings", "Paramètres"), ( "settings_save_err", "Impossible d'enregistrer les paramètres : {}", ), ("settings_saved", "Paramètres enregistrés"), ( "setup_intro", "Premier démarrage : créez le compte administrateur. Cet utilisateur peut gérer les autres utilisateurs et les paramètres du serveur.", ), ( "setup_pw_mismatch", "Les mots de passe ne correspondent pas.", ), ("share", "Partager"), ("share_create_err", "Impossible de créer le partage : {}"), ("share_delete_err", "Impossible de supprimer le partage"), ("share_deleted", "Partage supprimé"), ( "share_dialog_hint", "Crée un lien pour cet élément. Les liens modifiables permettent aux destinataires de téléverser et de modifier.", ), ("share_expired", "Partage expiré"), ("share_expired_msg", "Ce lien de partage n'est plus actif."), ("share_link", "Lien de partage"), ("share_locked_title", "Mot de passe requis"), ("share_not_found", "Partage introuvable"), ( "share_not_found_msg", "Ce lien est invalide ou le partage a été supprimé.", ), ("share_owner_disabled", "compte désactivé"), ( "share_password_hint", "Facultatif. Les visiteurs doivent le saisir avant d'ouvrir le partage, au moins 8 caractères.", ), ( "share_perm_ro", "Toute personne possédant ce lien peut lire « {} ».", ), ( "share_perm_rw", "Toute personne possédant ce lien peut lire et modifier « {} ».", ), ("share_protected", "Protégé par mot de passe"), ("share_title", "Partager {}"), ("shares", "Partages"), ("shares_delete_err", "Impossible de supprimer les partages"), ( "shares_empty_hint", "Faites un clic droit sur un fichier ou un dossier, puis choisissez « Partager » pour créer un lien.", ), ( "shares_view_hint", "Liens que vous avez créés. Faites un clic droit sur un fichier ou un dossier, puis choisissez « Partager » pour en ajouter un.", ), ("sign_in", "Se connecter"), ("signin_both", "Mot de passe et clé d'accès"), ( "signin_both_desc", "Les deux sont exigés. Le WebDAV exige alors un mot de passe d'application, car un montage ne peut envoyer qu'un mot de passe.", ), ("signin_either", "Mot de passe ou clé d'accès"), ( "signin_either_desc", "L'un ou l'autre suffit pour se connecter.", ), ("signin_requirement", "Exigence de connexion"), ( "single_click_desc", "Quand activé, un simple clic ouvre une entrée et Ctrl+clic la sélectionne. Quand désactivé, un simple clic sélectionne et un double-clic ouvre.", ), ("single_click_label", "Ouvrir au clic simple"), ("size", "Taille"), ("some_files_exist", "Certains fichiers existent déjà"), ("sort_asc", "Croissant"), ("sort_by", "Trier par"), ("sort_desc", "Décroissant"), ("theme_auto", "Auto"), ("theme_dark", "Sombre"), ("theme_light", "Clair"), ("theme_title", "Thème : {} (cliquer pour changer)"), ( "thumbnails_desc", "Afficher un aperçu à la place d'une icône pour les images et les vidéos en vue grille.", ), ("thumbnails_label", "Afficher les miniatures"), ("type", "Type"), ("unlock", "Ouvrir le partage"), ("unsaved_changes", "Modifications non enregistrées"), ("until", "Jusqu'au"), ("upload_abort", "Interrompre"), ("upload_aborted", "Interrompu"), ("upload_active_n", "{} en cours"), ( "upload_apply_all", "Appliquer aussi aux fichiers qui apparaissent pendant le téléversement", ), ( "upload_check_failed", "Impossible de vérifier les fichiers existants : {}", ), ("upload_clear", "Retirer de la liste"), ("upload_clear_finished", "Effacer les terminés"), ("upload_collapse", "Réduire"), ("upload_complete", "Téléversement terminé"), ( "upload_conflict_question", "Les fichiers suivants existent déjà. Les remplacer ou les ignorer ?", ), ("upload_drop_hint", "Déposer ici pour téléverser"), ("upload_errors_n", "{} en échec"), ( "upload_exists_ask", "« {} » est apparu sur le serveur pendant le téléversement.", ), ("upload_expand", "Développer"), ("upload_failed", "Échec"), ("upload_files", "Téléverser des fichiers"), ("upload_folder", "Téléverser un dossier"), ("upload_n_files", "{} fichiers"), ("upload_pause", "Mettre en pause"), ("upload_paused", "En pause"), ("upload_preparing", "Préparation…"), ("upload_resume", "Reprendre"), ("upload_show_graph", "Détails et graphique de vitesse"), ("upload_skip", "Ignorer"), ("upload_skipped_n", "{} ignorés"), ("upload_speed", "{}/s"), ("upload_waiting", "En attente de votre réponse"), ("uploads", "Téléversements"), ("uploads_empty", "Aucun téléversement pour l'instant"), ("use_passkey", "Utiliser une clé d'accès"), ( "use_passkey_hint", "Laissez le nom vide, sauf si votre clé d'accès en a besoin.", ), ("user_created", "Utilisateur créé"), ("user_delete_err", "Impossible de supprimer l'utilisateur"), ("user_disabled", "désactivé"), ("user_name_example", "p. ex. alice"), ( "user_save_err", "Impossible d'enregistrer l'utilisateur : {}", ), ("user_updated", "Utilisateur mis à jour"), ("user_you", "(vous)"), ("users", "Utilisateurs"), ("week_monday", "Lundi"), ("week_saturday", "Samedi"), ("week_start", "La semaine commence le"), ( "week_start_desc", "Le premier jour de la semaine dans le calendrier.", ), ("week_sunday", "Dimanche"), ("your_shares", "Vos partages"), ]; #[cfg(test)] mod tests { use super::*; fn keys<'a>(table: &'a [(&'a str, &'a str)]) -> Vec<&'a str> { table.iter().map(|(k, _)| *k).collect() } #[test] fn tables_are_sorted() { // `find` binary-searches, so an out-of-order entry is unreachable. for (name, table) in [("EN", EN), ("DE", DE), ("FR", FR)] { let ks = keys(table); let mut sorted = ks.clone(); sorted.sort_unstable(); assert_eq!(ks, sorted, "{name} table is not sorted by key"); } } #[test] fn no_duplicate_keys() { for (name, table) in [("EN", EN), ("DE", DE), ("FR", FR)] { let mut ks = keys(table); ks.sort_unstable(); let dups = ks .windows(2) .filter(|w| w[0] == w[1]) .map(|w| w[0]) .collect::>(); assert!(dups.is_empty(), "{name} duplicates: {dups:?}"); } } #[test] fn translations_cover_all_keys() { // Full parity: DE and FR must translate every EN key (both // directions), so no string can silently fall back to English. let en = keys(EN); for (name, table) in [("DE", DE), ("FR", FR)] { let other = keys(table); assert_eq!( en.len(), other.len(), "{name} has {} keys, EN has {}", other.len(), en.len() ); for k in &other { assert!(en.contains(k), "{name} key not in EN: {k}"); } } } }