i18n.rs
⎇
Raw
1//! Lightweight i18n: one central registry (in the spirit of `icons.rs`).
2//!
3//! `EN` is the canonical list of user-visible strings; it doubles as the key
4//! table. `DE` and `FR` translate the same keys; a key missing from a
5//! translation falls back to English.
6//!
7//! - `t(key)` resolves a key for the current locale. Non-reactive — for
8//! toasts, event handlers, and one-shot constructions (dialogs).
9//! - `tr(key)` is the same as a reactive closure, for `view!` children and
10//! attributes, so switching the language re-renders in place.
11//! - `error_text(code, fallback)` maps a server error *code* to a
12//! translation; unknown or absent codes fall back to the server message.
13//!
14//! Parameterized strings carry exactly one `{}` placeholder; callers do
15//! `format!(t(k::X), arg)`.
16//!
17//! Every table is sorted by key so lookups can binary-search.
18//!
19//! Locale precedence: the signed-in user's profile setting (persisted
20//! server-side), else the browser language. `init` + `set_locale` drive a
21//! global signal so every `tr` subscriber updates.
22
23use std::sync::OnceLock;
24
25use leptos::prelude::*;
26use wasm_bindgen::JsCast;
27
28/// A supported UI language.
29#[derive(Clone, Copy, PartialEq, Eq, Debug)]
30pub enum Locale {
31 En,
32 De,
33 Fr,
34}
35
36impl Locale {
37 pub const fn code(self) -> &'static str {
38 match self {
39 Locale::En => "en",
40 Locale::De => "de",
41 Locale::Fr => "fr",
42 }
43 }
44
45 /// Parse a BCP-47-ish tag ("de", "de-AT", "DE") into a supported locale.
46 pub fn from_code(code: &str) -> Option<Self> {
47 let lang = code.split(['-', '_']).next()?.to_ascii_lowercase();
48 match lang.as_str() {
49 "en" => Some(Locale::En),
50 "de" => Some(Locale::De),
51 "fr" => Some(Locale::Fr),
52 _ => None,
53 }
54 }
55
56 /// The browser's language, restricted to the supported locales.
57 pub fn from_browser() -> Option<Self> {
58 let lang = web_sys::window()?.navigator().language()?;
59 Self::from_code(&lang)
60 }
61}
62
63static READ: OnceLock<ReadSignal<Locale>> = OnceLock::new();
64static WRITE: OnceLock<WriteSignal<Locale>> = OnceLock::new();
65
66/// Called once during app setup, before the first UI render.
67pub fn init(locale: Locale) {
68 let (read, write) = signal(locale);
69 let _ = READ.set(read);
70 let _ = WRITE.set(write);
71 apply_doc_lang(locale);
72}
73
74pub fn set_locale(locale: Locale) {
75 if let Some(w) = WRITE.get() {
76 w.set(locale);
77 }
78 apply_doc_lang(locale);
79}
80
81pub fn current() -> Locale {
82 // Tracked inside a reactive scope, so views follow a language switch;
83 // outside one (event handlers, async tasks) a plain read, which Leptos
84 // would otherwise warn about.
85 let tracked = leptos::reactive::graph::Observer::get().is_some();
86 READ.get()
87 .map(|r| if tracked { r.get() } else { r.get_untracked() })
88 .unwrap_or(Locale::En)
89}
90
91/// Like [`current`] but without registering a reactive dependency — for
92/// code that reads the locale only to compare before writing (e.g. the
93/// profile effect in `app.rs`), so the read cannot retrigger itself.
94pub fn current_untracked() -> Locale {
95 READ.get().map(|r| r.get_untracked()).unwrap_or(Locale::En)
96}
97
98/// Keep `<html lang>` in sync for screen readers and the browser UI.
99fn apply_doc_lang(locale: Locale) {
100 if let Some(html) = web_sys::window()
101 .and_then(|w| w.document())
102 .and_then(|d| d.document_element())
103 .and_then(|e| e.dyn_into::<web_sys::HtmlElement>().ok())
104 {
105 let _ = html.set_attribute("lang", locale.code());
106 }
107}
108
109/// Resolve a key for the current locale (non-reactive).
110pub fn t(key: &str) -> &'static str {
111 text(key, current())
112}
113
114/// Resolve a key for the current locale as a reactive closure, for use as a
115/// `view!` child or attribute value.
116pub fn tr(key: &str) -> impl Fn() -> String + Clone {
117 move || t(key).to_string()
118}
119
120/// Like [`t`], but substitutes a single `{}` placeholder in the translation
121/// with `arg`.
122pub fn t_fmt(key: &str, arg: &str) -> String {
123 t(key).replace("{}", arg)
124}
125
126/// Like [`t_fmt`] for translations with two placeholders, filling the first
127/// `{}` with `a` and the second with `b`. Positional, so a locale that needs
128/// the other order has to reword rather than swap.
129pub fn t_fmt2(key: &str, a: &str, b: &str) -> String {
130 let s = t(key);
131 match s.split_once("{}") {
132 Some((head, tail)) => format!("{head}{a}{}", tail.replacen("{}", b, 1)),
133 None => s.to_string(),
134 }
135}
136
137/// Localize a server error: a known code maps to its translation, anything
138/// else (no code, unknown code) falls back to the server's English message.
139pub fn error_text(code: Option<&str>, fallback: &str) -> String {
140 let Some(code) = code.filter(|c| find(EN, c).is_some()) else {
141 return fallback.to_string();
142 };
143 // One-shot lookup for a toast message: no reactive context, so read the
144 // locale untracked.
145 text(code, current_untracked()).to_string()
146}
147
148fn text(key: &str, locale: Locale) -> &'static str {
149 // Keys are compile-time constants from `k`; a miss is a bug (the unit
150 // tests pin the tables against each other).
151 match locale {
152 Locale::En => find(EN, key).expect("unknown i18n key"),
153 Locale::De => find(DE, key)
154 .or_else(|| find(EN, key))
155 .expect("unknown i18n key"),
156 Locale::Fr => find(FR, key)
157 .or_else(|| find(EN, key))
158 .expect("unknown i18n key"),
159 }
160}
161
162/// The tables are sorted by key, so a lookup is a binary search. The
163/// `tables_are_sorted` test keeps that invariant true.
164fn find(table: &'static [(&'static str, &'static str)], key: &str) -> Option<&'static str> {
165 table
166 .binary_search_by(|(k, _)| (*k).cmp(key))
167 .ok()
168 .map(|i| table[i].1)
169}
170
171/// Declares the translation keys and the canonical English text in one
172/// place: one row per key, `CONST = "key" => "English"`.
173///
174/// The `k` constants and the `EN` table are generated from the same row, so
175/// a key cannot exist in one without the other. Rows are sorted by key,
176/// because [`find`] binary-searches (`tables_are_sorted` pins that).
177macro_rules! i18n_keys {
178 ($($name:ident = $key:literal => $en:expr),* $(,)?) => {
179 /// Translation keys. Use these, never the raw strings: a typo in a
180 /// key is a compile error, a typo in a string is a runtime panic.
181 pub mod k {
182 $(pub const $name: &str = $key;)*
183 }
184
185 /// Canonical English strings (key → text). The source of truth for
186 /// which keys exist; DE and FR translate the same list.
187 const EN: &[(&str, &str)] = &[$(($key, $en)),*];
188 };
189}
190
191i18n_keys! {
192 ACTIVE_CAN_SIGNIN = "active_can_signin" => "Active (can sign in)",
193 ADD_APP_PASSWORD = "add_app_password" => "Create app password",
194 ADD_FOLDER = "add_folder" => "Add folder…",
195 ADD_HERE = "add_here" => "Add this folder",
196 ADD_PASSKEY = "add_passkey" => "Add passkey",
197 ADMINISTRATOR = "administrator" => "Administrator",
198 ALL_SHARES = "all_shares" => "All shares",
199 ALL_SHARES_HINT = "all_shares_hint" => "Every link on this server, grouped by the account that created it.",
200 ALLOW_EDITING = "allow_editing" => "Allow editing (read-write)",
201 ALLOW_RW_SHARES = "allow_rw_shares" => "Allow writable shares",
202 ALLOW_RW_SHARES_DESC = "allow_rw_shares_desc" => "Let users create read-write share links. Off by default.",
203 AND_MORE = "and_more" => "…and {} more",
204 APP_PASSWORD_LABEL = "app_password_label" => "Name for this app password",
205 APP_PASSWORD_REMOVED = "app_password_removed" => "App password revoked",
206 APP_PASSWORD_SECRET_ONCE = "app_password_secret_once" => "Copy it now. It is never shown again.",
207 APP_PASSWORDS = "app_passwords" => "App passwords",
208 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.",
209 CANCEL = "cancel" => "Cancel",
210 CANT_DELETE_SELF = "cant_delete_self" => "You cannot delete yourself",
211 CLOSE = "close" => "Close",
212 CLOSE_ESC = "close_esc" => "Close (Esc)",
213 COPIED = "copied" => "Copied",
214 COPY = "copy" => "Copy",
215 COPY_DAV_LINK = "copy_dav_link" => "Copy WebDAV link",
216 COPY_HERE = "copy_here" => "Copy here",
217 COPY_LINK = "copy_link" => "Copy link",
218 COPY_MANUAL = "copy_manual" => "Copy the link manually",
219 COPY_N_TO = "copy_n_to" => "Copy {} items to…",
220 COPY_TO = "copy_to" => "Copy “{}” to…",
221 CREATE = "create" => "Create",
222 CREATE_ADMIN = "create_admin" => "Create admin account",
223 CREATE_LINK = "create_link" => "Create link",
224 CREATE_USER = "create_user" => "Create user",
225 CREATING = "creating" => "Creating…",
226 CT_TYPE_CELL = "ct_type_cell" => "mobile",
227 CT_TYPE_FAX = "ct_type_fax" => "fax",
228 CT_TYPE_HOME = "ct_type_home" => "home",
229 CT_TYPE_OTHER = "ct_type_other" => "other",
230 CT_TYPE_WORK = "ct_type_work" => "work",
231 CUSTOM = "custom" => "Custom…",
232 DEFAULT_ROOT_DESC = "default_root_desc" => "Open this folder on page load and on the home link.",
233 DEFAULT_ROOT_LABEL = "default_root_label" => "Default folder",
234 DEFAULT_ROOT_NONE = "default_root_none" => "Folder overview",
235 DELETE = "delete" => "Delete",
236 DELETE_ALL = "delete_all" => "Delete all",
237 DELETE_ALL_MSG = "delete_all_msg" => "Delete all {} share links? Anyone holding them loses access. This cannot be undone.",
238 DELETE_ALL_TITLE = "delete_all_title" => "Delete all shares?",
239 DELETE_ALL_USER_MSG = "delete_all_user_msg" => "Delete every share link of “{}”? Anyone holding them loses access. This cannot be undone.",
240 DELETE_FOLDER_MSG = "delete_folder_msg" => "Delete folder “{}” and everything inside it?\nThis cannot be undone.",
241 DELETE_MSG = "delete_msg" => "Delete “{}”?\nThis cannot be undone.",
242 DELETE_N_MSG = "delete_n_msg" => "Delete {} items?\nThis cannot be undone.",
243 DELETE_PARTIAL = "delete_partial" => "{} of {} shares could not be deleted",
244 DELETE_SHARE = "delete_share" => "Delete share",
245 DELETE_USER = "delete_user" => "Delete user",
246 DELETE_USER_CONFIRM = "delete_user_confirm" => "Delete user “{}”? This cannot be undone.",
247 DELETED = "deleted" => "Deleted",
248 DELETED_N_SHARES = "deleted_n_shares" => "Deleted {} shares",
249 DISCARD = "discard" => "Discard",
250 DISCARD_QUESTION = "discard_question" => "Discard your changes and close the editor?",
251 DISMISS = "dismiss" => "Dismiss",
252 DISMISS_ERROR = "dismiss_error" => "Dismiss error",
253 DONE = "done" => "Done",
254 DOWNLOAD = "download" => "Download",
255 DOWNLOAD_FORMATS_MSG = "download_formats_msg" => "Choose an archive format for the folder.",
256 DOWNLOAD_STARTED = "download_started" => "Download started",
257 DOWNLOAD_TITLE = "download_title" => "Download “{}”",
258 EDIT = "edit" => "Edit",
259 EDIT_USER_TITLE = "edit_user_title" => "Edit “{}”",
260 EMPTY_FOLDER = "empty_folder" => "This folder is empty.",
261 ERR_ADMIN_ONLY = "err_admin_only" => "admin only",
262 ERR_ALREADY_SET_UP = "err_already_set_up" => "server is already set up",
263 ERR_APP_PASSWORD_LIMIT = "err_app_password_limit" => "This account already has as many app passwords as it may.",
264 ERR_APP_PASSWORD_NOT_FOUND = "err_app_password_not_found" => "No such app password.",
265 ERR_BAD_ACTION = "err_bad_action" => "expected action=content",
266 ERR_BAD_BODY = "err_bad_body" => "invalid request body",
267 ERR_BAD_EXPIRES_AT = "err_bad_expires_at" => "the expiry date is invalid",
268 ERR_BAD_FORMAT = "err_bad_format" => "format must be one of: zip, tar, tar.gz, tar.zst",
269 ERR_BAD_MULTIPART = "err_bad_multipart" => "expected multipart/form-data with a boundary",
270 ERR_BAD_PART_NAME = "err_bad_part_name" => "invalid part name",
271 ERR_BAD_POST = "err_bad_post" => "POST expects a multipart upload, a JSON mutation, or ?action=mkdir/create-file",
272 ERR_BAD_UPLOAD = "err_bad_upload" => "invalid upload data",
273 ERR_BAD_UPLOAD_PATH = "err_bad_upload_path" => "invalid file path in upload",
274 ERR_CHALLENGE_EXPIRED = "err_challenge_expired" => "That took too long, please try again.",
275 ERR_DEFAULT_CALENDAR = "err_default_calendar" => "The calendar that receives invitations cannot be deleted.",
276 ERR_DST_REQUIRED = "err_dst_required" => "dst_root_id is required",
277 ERR_FILE_NAME_REQUIRED = "err_file_name_required" => "a file name is required",
278 ERR_FILES_EXIST = "err_files_exist" => "some files already exist",
279 ERR_FOLDER_EXISTS = "err_folder_exists" => "a folder with this name already exists",
280 ERR_FOLDER_NAME_REQUIRED = "err_folder_name_required" => "a folder name is required",
281 ERR_FS_CONFLICT = "err_fs_conflict" => "already exists",
282 ERR_FS_FORBIDDEN = "err_fs_forbidden" => "access denied",
283 ERR_FS_NOT_A_DIR = "err_fs_not_a_dir" => "not a folder",
284 ERR_FS_NOT_FOUND = "err_fs_not_found" => "folder not found",
285 ERR_FS_ROOT_MISSING = "err_fs_root_missing" => "the configured folder no longer exists",
286 ERR_INTERNAL = "err_internal" => "internal error",
287 ERR_INVALID_CREDENTIALS = "err_invalid_credentials" => "invalid name or password",
288 ERR_INVALID_DEFAULT_ROOT = "err_invalid_default_root" => "the default folder is not one of your folders",
289 ERR_INVALID_LANGUAGE = "err_invalid_language" => "invalid language tag",
290 ERR_INVALID_WEEK_START = "err_invalid_week_start" => "invalid week start",
291 ERR_LAST_ADMIN = "err_last_admin" => "cannot remove the last active admin",
292 ERR_LAST_ADMIN_DELETE = "err_last_admin_delete" => "cannot delete the last active admin",
293 ERR_LOCKED_OUT = "err_locked_out" => "That would leave the account with no way to sign in.",
294 ERR_MODE_NEEDS_PASSKEY = "err_mode_needs_passkey" => "Add a passkey before requiring both.",
295 ERR_MODE_NEEDS_PASSWORD = "err_mode_needs_password" => "Set a password before requiring both.",
296 ERR_NAME_LENGTH = "err_name_length" => "name must be 1–64 characters",
297 ERR_NEW_NAME_REQUIRED = "err_new_name_required" => "new_name is required",
298 ERR_NO_FILES_UPLOADED = "err_no_files_uploaded" => "no files were uploaded",
299 ERR_NO_SUCH_FOLDER = "err_no_such_folder" => "no such folder",
300 ERR_NOT_A_FILE = "err_not_a_file" => "not a file",
301 ERR_NOT_SIGNED_IN = "err_not_signed_in" => "not signed in",
302 ERR_OWN_ACCOUNT = "err_own_account" => "you cannot disable your own account",
303 ERR_OWN_ADMIN = "err_own_admin" => "you cannot remove your own admin rights",
304 ERR_OWN_DELETE = "err_own_delete" => "you cannot delete your own account",
305 ERR_PART_NO_NAME = "err_part_no_name" => "part without a name",
306 ERR_PASSKEY_DUPLICATE = "err_passkey_duplicate" => "That passkey is already registered.",
307 ERR_PASSKEY_FAILED = "err_passkey_failed" => "That passkey could not be used.",
308 ERR_PASSKEY_LAST_CREDENTIAL = "err_passkey_last_credential" => "Set a password before removing your last passkey.",
309 ERR_PASSKEY_LIMIT = "err_passkey_limit" => "This account already has as many passkeys as it may.",
310 ERR_PASSKEY_MALFORMED = "err_passkey_malformed" => "The browser sent unreadable data.",
311 ERR_PASSKEY_NOT_FOUND = "err_passkey_not_found" => "No such passkey.",
312 ERR_PASSKEY_ORIGIN = "err_passkey_origin" => "Passkeys are set up for a different address.",
313 ERR_PASSKEY_UNAVAILABLE = "err_passkey_unavailable" => "Passkeys are not available here.",
314 ERR_PASSWORD_LAST_CREDENTIAL = "err_password_last_credential" => "Add a passkey before removing your password.",
315 ERR_PASSWORD_SHORT = "err_password_short" => "password must be at least 8 characters",
316 ERR_PATH_REQUIRED = "err_path_required" => "a path inside the folder is required",
317 ERR_READ_ONLY_FOLDER = "err_read_only_folder" => "read-only folder",
318 ERR_REQUIRED_BY_MODE = "err_required_by_mode" => "This account requires a password and a passkey.",
319 ERR_ROOT_FORBIDDEN = "err_root_forbidden" => "root not accessible",
320 ERR_RW_RO_FOLDER = "err_rw_ro_folder" => "this folder is read-only for you, so it cannot be shared writably",
321 ERR_RW_SHARES_DISABLED = "err_rw_shares_disabled" => "writable shares are disabled",
322 ERR_SAVE_FAILED = "err_save_failed" => "could not save the file",
323 ERR_SEARCH_BAD_SCOPE = "err_search_bad_scope" => "scope must be name, content or both",
324 ERR_SEARCH_FORBIDDEN = "err_search_forbidden" => "search requires a signed-in session",
325 ERR_SESSION_EXPIRED = "err_session_expired" => "session expired, please sign in again",
326 ERR_SHARE_EXPIRED = "err_share_expired" => "this share has expired",
327 ERR_SHARE_LOCKED = "err_share_locked" => "This share is password protected.",
328 ERR_SHARE_NO_PASSWORD = "err_share_no_password" => "This share has no password.",
329 ERR_SHARE_NOT_FOUND = "err_share_not_found" => "share not found",
330 ERR_SHARE_TOKEN_FORBIDDEN = "err_share_token_forbidden" => "a share token cannot be used here; sign in instead",
331 ERR_SHARE_WRONG_PASSWORD = "err_share_wrong_password" => "Wrong password.",
332 ERR_TOO_LARGE_PREVIEW = "err_too_large_preview" => "file too large to preview",
333 ERR_TOO_LARGE_SAVE = "err_too_large_save" => "file too large to save",
334 ERR_USER_EXISTS = "err_user_exists" => "a user with that name already exists",
335 ERR_USER_NOT_FOUND = "err_user_not_found" => "user not found",
336 EXCLUDE_DUP_ERR = "exclude_dup_err" => "That folder is already excluded.",
337 EXCLUDE_FOLDER = "exclude_folder" => "Exclude folder…",
338 EXCLUDE_HERE = "exclude_here" => "Exclude this folder",
339 EXCLUDE_ROOT_ERR = "exclude_root_err" => "The whole root cannot be excluded; that would turn search off.",
340 EXPIRES = "expires" => "Expires",
341 EXPIRES_AT = "expires_at" => "Expires {}",
342 EXPIRY_1D = "expiry_1d" => "1 day",
343 EXPIRY_1H = "expiry_1h" => "1 hour",
344 EXPIRY_1MO = "expiry_1mo" => "1 month",
345 EXPIRY_1W = "expiry_1w" => "1 week",
346 FILE = "file" => "File",
347 FILE_CHANGED = "file_changed" => "File changed on disk",
348 FILE_CREATED = "file_created" => "File created",
349 FILE_INFO = "file_info" => "File info",
350 FILE_NAME = "file_name" => "File name",
351 FILE_NOT_FOUND = "file_not_found" => "File not found",
352 FILES = "files" => "Files",
353 FMT_TAR = "fmt_tar" => "Tar",
354 FMT_TARGZ = "fmt_targz" => "Tar + gzip",
355 FMT_TARZST = "fmt_tarzst" => "Tar + zstd",
356 FMT_ZIP = "fmt_zip" => "Zip",
357 FOLDER = "folder" => "Folder",
358 FOLDER_CREATED = "folder_created" => "Folder created",
359 FOLDER_GONE_MSG = "folder_gone_msg" => "This folder is no longer accessible. Choose another one from the sidebar.",
360 FOLDER_GONE_TITLE = "folder_gone_title" => "Folder not available",
361 FOLDER_NAME = "folder_name" => "Folder name",
362 FOLDERS = "folders" => "Folders",
363 FOLDERS_PATHS_HINT = "folders_paths_hint" => "Paths are relative to the server root. “.” is the whole root.",
364 GRID_VIEW = "grid_view" => "Grid view",
365 INFO = "info" => "Info",
366 KEEP_EDITING = "keep_editing" => "Keep editing",
367 LANG_AUTO = "lang_auto" => "Automatic",
368 LANG_DE = "lang_de" => "German",
369 LANG_EN = "lang_en" => "English",
370 LANG_FR = "lang_fr" => "French",
371 LANGUAGE = "language" => "Language",
372 LANGUAGE_DESC = "language_desc" => "The interface language. Automatic uses your browser's language.",
373 LINK_COPIED = "link_copied" => "Link copied to clipboard",
374 LIST_VIEW = "list_view" => "List view",
375 LOAD_LATEST = "load_latest" => "Load latest",
376 LOADING = "loading" => "Loading…",
377 LOADING_SHARE = "loading_share" => "Loading share…",
378 LOCATION = "location" => "Location",
379 LOG_OUT = "log_out" => "Log out",
380 LOGIN_SUBTITLE = "login_subtitle" => "Sign in to continue.",
381 MANAGE = "manage" => "Manage",
382 MENU = "menu" => "Menu",
383 META_CREATED = "meta_created" => "created {}",
384 META_EXPIRES = "meta_expires" => "expires {}",
385 MODE_RO = "mode_ro" => "read-only",
386 MODE_RW = "mode_rw" => "read-write",
387 MODIFIED = "modified" => "Modified",
388 MODIFIED_AFTER = "modified_after" => "This file was modified after you opened it. “Load latest” discards your unsaved changes; “Overwrite” keeps your version.",
389 MORE_ACTIONS = "more_actions" => "More actions",
390 MOVE = "move" => "Move",
391 MOVE_HERE = "move_here" => "Move here",
392 MOVE_N_TO = "move_n_to" => "Move {} items to…",
393 MOVE_TO = "move_to" => "Move “{}” to…",
394 MOVED = "moved" => "Moved",
395 NAME = "name" => "Name",
396 NAME_TAKEN = "name_taken" => "Name already in use",
397 NEED_FOLDER = "need_folder" => "Give the user at least one folder.",
398 NEVER = "never" => "Never",
399 NEVER_EXPIRES = "never_expires" => "Never expires",
400 NEW_FILE = "new_file" => "New file",
401 NEW_FOLDER = "new_folder" => "New folder",
402 NEW_NAME = "new_name" => "New name",
403 NEW_PASSWORD = "new_password" => "New password",
404 NEW_PASSWORD_HINT = "new_password_hint" => "Leave empty to keep your current password.",
405 NEW_PASSWORD_KEEP = "new_password_keep" => "New password (leave blank to keep)",
406 NEW_USER = "new_user" => "New user",
407 NO_APP_PASSWORDS = "no_app_passwords" => "No app passwords.",
408 NO_FOLDERS_MSG = "no_folders_msg" => "An administrator hasn't assigned you any folders yet.",
409 NO_FOLDERS_TITLE = "no_folders_title" => "No folders available",
410 NO_PASSKEYS = "no_passkeys" => "No passkeys yet.",
411 NO_PASSWORD_SET = "no_password_set" => "This account signs in with passkeys only.",
412 NO_PREVIEW = "no_preview" => "No preview available",
413 NO_PREVIEW_MSG = "no_preview_msg" => "The app can’t display “{}” here.",
414 NO_SHARES = "no_shares" => "No shares yet",
415 NO_SUBFOLDERS = "no_subfolders" => "No subfolders",
416 NO_USERS = "no_users" => "No users.",
417 OPEN = "open" => "Open",
418 OPEN_IN_NEW_TAB = "open_in_new_tab" => "Open in new tab",
419 OPEN_MENU = "open_menu" => "Open menu",
420 OR_LABEL = "or_label" => "or",
421 OVERWRITE = "overwrite" => "Overwrite",
422 OVERWRITE_QUESTION = "overwrite_question" => "The following files already exist. Overwrite them?",
423 PAGE_FIRST = "page_first" => "First page",
424 PAGE_GOTO = "page_goto" => "Page",
425 PAGE_LAST = "page_last" => "Last page",
426 PAGE_NEXT = "page_next" => "Next page",
427 PAGE_PREV = "page_prev" => "Previous page",
428 PAGE_SIZE = "page_size" => "Entries per page",
429 PAGE_SIZE_N = "page_size_n" => "{} per page",
430 PASSKEY_ADDED = "passkey_added" => "Passkey added",
431 PASSKEY_ADDED_ON = "passkey_added_on" => "Added {}",
432 PASSKEY_LABEL = "passkey_label" => "Name for this passkey",
433 PASSKEY_LAST_USED = "passkey_last_used" => "Last used {}",
434 PASSKEY_NEEDS_NAME = "passkey_needs_name" => "Needs your user name",
435 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.",
436 PASSKEY_NEVER_USED = "passkey_never_used" => "Never used",
437 PASSKEY_NOT_USED = "passkey_not_used" => "No passkey was used.",
438 PASSKEY_REMOVED = "passkey_removed" => "Passkey removed",
439 PASSKEY_UNSUPPORTED = "passkey_unsupported" => "This browser cannot use passkeys.",
440 PASSKEYS = "passkeys" => "Passkeys",
441 PASSKEYS_HINT = "passkeys_hint" => "A passkey signs you in with your fingerprint, your face or a security key.",
442 PASSWORD = "password" => "Password",
443 PASSWORD_MIN_HINT = "password_min_hint" => "at least 8 characters",
444 PASSWORD_REMOVED = "password_removed" => "Password removed",
445 PASSWORD_RESETS_SIGNIN = "password_resets_signin" => "Setting a password also deletes this account's passkeys and drops any two-factor requirement.",
446 PIM_ACCEPT = "pim_accept" => "Accept",
447 PIM_ACCESS = "pim_access" => "Access",
448 PIM_ADD = "pim_add" => "Add",
449 PIM_ADDRESS = "pim_address" => "Address for apps",
450 PIM_ADDRESS_BOOK = "pim_address_book" => "Address book",
451 PIM_ADDRESS_BOOKS = "pim_address_books" => "Address books",
452 PIM_AGENDA = "pim_agenda" => "Agenda",
453 PIM_ALL_DAY = "pim_all_day" => "All day",
454 PIM_ALL_EVENTS = "pim_all_events" => "All events of the series",
455 PIM_ANNIVERSARY = "pim_anniversary" => "Anniversary",
456 PIM_APP_PASSWORDS = "pim_app_passwords" => "Create an app password",
457 PIM_ATTENDEES = "pim_attendees" => "Attendees",
458 PIM_AUTO = "pim_auto" => "automatic",
459 PIM_BACK = "pim_back" => "Back",
460 PIM_BIRTHDAY = "pim_birthday" => "Birthday",
461 PIM_BIRTHDAYS = "pim_birthdays" => "Birthdays",
462 PIM_CALENDAR = "pim_calendar" => "Calendar",
463 PIM_CALENDARS = "pim_calendars" => "Calendars",
464 PIM_CANCELLED = "pim_cancelled" => "Cancelled",
465 PIM_CATEGORIES = "pim_categories" => "Categories",
466 PIM_CLIENTS = "pim_clients" => "Apps",
467 PIM_COLLECTION_URLS = "pim_collection_urls" => "Addresses of single calendars and address books",
468 PIM_COLOR = "pim_color" => "Color",
469 PIM_CONNECT = "pim_connect" => "Connect an app",
470 PIM_CONNECT_TITLE = "pim_connect_title" => "Connect a calendar or contacts app",
471 PIM_CONTACTS = "pim_contacts" => "Contacts",
472 PIM_CREATED = "pim_created" => "Created",
473 PIM_CUSTOM_COLOR = "pim_custom_color" => "Custom color",
474 PIM_DECLINE = "pim_decline" => "Decline",
475 PIM_DEFAULT_HINT = "pim_default_hint" => "This calendar receives invitations. It cannot be deleted.",
476 PIM_DELETE_MSG = "pim_delete_msg" => "Everything in it is deleted. The attendees of your meetings get a cancellation.",
477 PIM_DELETE_TITLE = "pim_delete_title" => "Delete “{}”?",
478 PIM_DESCRIPTION = "pim_description" => "Description",
479 PIM_DETAIL = "pim_detail" => "Details",
480 PIM_DETAIL_BUSY = "pim_detail_busy" => "Busy times only",
481 PIM_DETAIL_FULL = "pim_detail_full" => "All details",
482 PIM_DIRECTORY = "pim_directory" => "Directory",
483 PIM_EMAIL = "pim_email" => "Email",
484 PIM_EVENTS_N = "pim_events_n" => "{} events",
485 PIM_EVENTS_ONE = "pim_events_one" => "1 event",
486 PIM_EXPORT = "pim_export" => "Export",
487 PIM_FEEDS_OF = "pim_feeds_of" => "Feeds of {}",
488 PIM_FILE = "pim_file" => "File",
489 PIM_FROM_ORGANIZER = "pim_from_organizer" => "From {}",
490 PIM_FROM_TIME = "pim_from_time" => "from {}",
491 PIM_GENERAL = "pim_general" => "General",
492 PIM_GENERATED_HINT = "pim_generated_hint" => "The server fills this in. It is read-only.",
493 PIM_GROUP = "pim_group" => "Group",
494 PIM_HIDE = "pim_hide" => "Hide",
495 PIM_HINT_APPLE = "pim_hint_apple" => "Apple: add a CalDAV and a CardDAV account with the server address. Apple needs HTTPS.",
496 PIM_HINT_DAVX5 = "pim_hint_davx5" => "Android: in DAVx⁵, sign in with URL and user name, and use the server address.",
497 PIM_HINT_GNOME = "pim_hint_gnome" => "GNOME and Evolution: add a CalDAV or WebDAV account with the server address.",
498 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.",
499 PIM_IMPORT = "pim_import" => "Import",
500 PIM_IMPORT_DONE = "pim_import_done" => "{} new, {} updated.",
501 PIM_IMPORT_FILE = "pim_import_file" => "Import file…",
502 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.",
503 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.",
504 PIM_IMPORT_NEW_HINT_CAL = "pim_import_new_hint_cal" => "Creates a calendar with the events of an .ics file.",
505 PIM_IMPORT_NEW_HINT_CARDS = "pim_import_new_hint_cards" => "Creates an address book with the contacts of a .vcf file.",
506 PIM_IMPORT_NOTHING = "pim_import_nothing" => "Nothing could be imported, so nothing was created.",
507 PIM_IMPORT_SKIPPED = "pim_import_skipped" => "{} skipped:",
508 PIM_IMPORTED_AS = "pim_imported_as" => "Imported as “{}”.",
509 PIM_IMPORTING = "pim_importing" => "Importing…",
510 PIM_INV_SERIES_HINT = "pim_inv_series_hint" => "Your answer applies to the whole series.",
511 PIM_INVITATIONS = "pim_invitations" => "Invitations",
512 PIM_KIND_RESOURCE = "pim_kind_resource" => "Resource",
513 PIM_KIND_ROOM = "pim_kind_room" => "Room",
514 PIM_LINK = "pim_link" => "Link",
515 PIM_LINK_BUSY = "pim_link_busy" => "busy times only",
516 PIM_LINK_FULL = "pim_link_full" => "all details",
517 PIM_LINK_REVOKED = "pim_link_revoked" => "Link revoked",
518 PIM_LINKS = "pim_links" => "Public links",
519 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.",
520 PIM_LINKS_HINT_CARDS = "pim_links_hint_cards" => "Anyone with the link can download the contacts once. Apps do not follow changes.",
521 PIM_LOCATION = "pim_location" => "Location",
522 PIM_MANAGE = "pim_manage" => "Settings",
523 PIM_MANAGE_OF = "pim_manage_of" => "Settings for {}",
524 PIM_MEMBERS = "pim_members" => "Members",
525 PIM_MODE_RO = "pim_mode_ro" => "Read only",
526 PIM_MODE_RW = "pim_mode_rw" => "Read and write",
527 PIM_MODE_SCHEDULE = "pim_mode_schedule" => "Read, write and send invitations",
528 PIM_MONTH = "pim_month" => "Month",
529 PIM_MORE_N = "pim_more_n" => "+{} more",
530 PIM_NAME_FROM_FILE = "pim_name_from_file" => "From the file if empty",
531 PIM_NAV = "pim_nav" => "Calendar & contacts",
532 PIM_NEW_ADDRESS_BOOK = "pim_new_address_book" => "New address book",
533 PIM_NEW_BOOK_FROM_FILE = "pim_new_book_from_file" => "New address book from file",
534 PIM_NEW_CALENDAR = "pim_new_calendar" => "New calendar",
535 PIM_NEW_CALENDAR_FROM_FILE = "pim_new_calendar_from_file" => "New calendar from file",
536 PIM_NEW_FROM_FILE = "pim_new_from_file" => "New from file…",
537 PIM_NEW_ROOM = "pim_new_room" => "New room",
538 PIM_NEXT_MONTH = "pim_next_month" => "Next month",
539 PIM_NO_CONTACTS = "pim_no_contacts" => "No contacts yet. Add some with a contacts app or an import.",
540 PIM_NO_EVENTS_AGENDA = "pim_no_events_agenda" => "No events in the next 7 days.",
541 PIM_NO_EVENTS_DAY = "pim_no_events_day" => "No events on this day.",
542 PIM_NO_INVITATIONS = "pim_no_invitations" => "No open invitations.",
543 PIM_NO_LINKS = "pim_no_links" => "No public links.",
544 PIM_NO_MATCH = "pim_no_match" => "No contact matches.",
545 PIM_NO_ROOMS = "pim_no_rooms" => "No rooms or resources.",
546 PIM_NO_SHARES = "pim_no_shares" => "Not shared with anyone.",
547 PIM_NO_TITLE = "pim_no_title" => "(no title)",
548 PIM_NOT_CONTACT = "pim_not_contact" => "This entry is not a contact.",
549 PIM_NOT_EVENT = "pim_not_event" => "This entry is not an event.",
550 PIM_NOTE = "pim_note" => "Note",
551 PIM_OPTIONAL = "pim_optional" => "optional",
552 PIM_ORGANIZER = "pim_organizer" => "Organizer",
553 PIM_OWN_EMPTY = "pim_own_empty" => "No public links, and nothing shared with other users.",
554 PIM_OWN_HINT = "pim_own_hint" => "Public links to your calendars and address books, and what you share with other users. Each collection's settings manage them too.",
555 PIM_OWN_LENDS = "pim_own_lends" => "Shared with other users",
556 PIM_OWN_LINKS = "pim_own_links" => "Your public links",
557 PIM_PASSWORD_HINT = "pim_password_hint" => "Use an app password rather than your account password.",
558 PIM_PHONE = "pim_phone" => "Phone",
559 PIM_PICK_CONTACT = "pim_pick_contact" => "Choose a contact to see the details.",
560 PIM_POSTAL = "pim_postal" => "Address",
561 PIM_PREV_MONTH = "pim_prev_month" => "Previous month",
562 PIM_PS_ACCEPTED = "pim_ps_accepted" => "Accepted",
563 PIM_PS_DECLINED = "pim_ps_declined" => "Declined",
564 PIM_PS_DELEGATED = "pim_ps_delegated" => "Delegated",
565 PIM_PS_NEEDS_ACTION = "pim_ps_needs_action" => "No answer yet",
566 PIM_PS_TENTATIVE = "pim_ps_tentative" => "Maybe",
567 PIM_RECEIVES_INVITATIONS = "pim_receives_invitations" => "Receives invitations",
568 PIM_REMOVE_FROM_LIST = "pim_remove_from_list" => "Remove from my list",
569 PIM_REMOVE_MSG = "pim_remove_msg" => "You no longer see it. The owner can share it again.",
570 PIM_REMOVED = "pim_removed" => "Removed from your list",
571 PIM_REPEATS = "pim_repeats" => "Repeats",
572 PIM_REPLIED = "pim_replied" => "Answer sent",
573 PIM_ROOM_DELETE_CONFIRM = "pim_room_delete_confirm" => "Delete “{}”? Its bookings are lost.",
574 PIM_ROOM_DISPLAY = "pim_room_display" => "Display name",
575 PIM_ROOM_NAME = "pim_room_name" => "Name (part of its address, cannot change)",
576 PIM_ROOMS = "pim_rooms" => "Rooms and resources",
577 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.",
578 PIM_RRULE_COUNT = "pim_rrule_count" => "{} times",
579 PIM_RRULE_DAILY = "pim_rrule_daily" => "Every day",
580 PIM_RRULE_DAILY_N = "pim_rrule_daily_n" => "Every {} days",
581 PIM_RRULE_LAST_DAY = "pim_rrule_last_day" => "last day",
582 PIM_RRULE_MONTH_DAY = "pim_rrule_month_day" => "day {}",
583 PIM_RRULE_MONTHLY = "pim_rrule_monthly" => "Every month",
584 PIM_RRULE_MONTHLY_N = "pim_rrule_monthly_n" => "Every {} months",
585 PIM_RRULE_NTH = "pim_rrule_nth" => "{} {}",
586 PIM_RRULE_ORD_1 = "pim_rrule_ord_1" => "1st",
587 PIM_RRULE_ORD_2 = "pim_rrule_ord_2" => "2nd",
588 PIM_RRULE_ORD_3 = "pim_rrule_ord_3" => "3rd",
589 PIM_RRULE_ORD_4 = "pim_rrule_ord_4" => "4th",
590 PIM_RRULE_ORD_5 = "pim_rrule_ord_5" => "5th",
591 PIM_RRULE_ORD_LAST = "pim_rrule_ord_last" => "last",
592 PIM_RRULE_UNTIL = "pim_rrule_until" => "until {}",
593 PIM_RRULE_WEEKLY = "pim_rrule_weekly" => "Every week",
594 PIM_RRULE_WEEKLY_N = "pim_rrule_weekly_n" => "Every {} weeks",
595 PIM_RRULE_YEARLY = "pim_rrule_yearly" => "Every year",
596 PIM_RRULE_YEARLY_N = "pim_rrule_yearly_n" => "Every {} years",
597 PIM_SAVE_ERR = "pim_save_err" => "Could not save: {}",
598 PIM_SEARCH_CONTACTS = "pim_search_contacts" => "Search contacts",
599 PIM_SERVER_ADDRESS = "pim_server_address" => "Server address",
600 PIM_SERVER_ADDRESS_HINT = "pim_server_address_hint" => "If an app does not find the server, use this address:",
601 PIM_SHARED_BY = "pim_shared_by" => "Shared by {}",
602 PIM_SHARED_OK = "pim_shared_ok" => "Shared with {}",
603 PIM_SHARED_WITH_ME = "pim_shared_with_me" => "Shared with me",
604 PIM_SHARING = "pim_sharing" => "Sharing",
605 PIM_SHARING_HINT = "pim_sharing_hint" => "Share with another account on this server.",
606 PIM_SHOW = "pim_show" => "Show",
607 PIM_SHOW_ALL = "pim_show_all" => "Show all",
608 PIM_SHOW_ONLY = "pim_show_only" => "Show only this one",
609 PIM_SKIP_COMPONENT = "pim_skip_component" => "this type is not accepted here",
610 PIM_SKIP_INVALID = "pim_skip_invalid" => "invalid or incomplete data",
611 PIM_SKIP_SIZE = "pim_skip_size" => "too large",
612 PIM_SKIP_UID = "pim_skip_uid" => "the same UID is already in another calendar",
613 PIM_SUBSCRIBE = "pim_subscribe" => "Subscribe",
614 PIM_TENTATIVE = "pim_tentative" => "Maybe",
615 PIM_THIS_EVENT = "pim_this_event" => "Only this event",
616 PIM_TODAY = "pim_today" => "Today",
617 PIM_TRANSPARENT = "pim_transparent" => "Show as free: events do not block time slots in invitations",
618 PIM_TRUNCATED = "pim_truncated" => "Not every event fits into this view. Hide some calendars to see the rest.",
619 PIM_UNSHARE = "pim_unshare" => "Stop sharing",
620 PIM_UNSHARED = "pim_unshared" => "No longer shared",
621 PIM_UNTIL_TIME = "pim_until_time" => "until {}",
622 PIM_UPCOMING = "pim_upcoming" => "Next 7 days",
623 PIM_USER = "pim_user" => "User name",
624 PIM_USER_NAME = "pim_user_name" => "User name",
625 PIM_WEBSITE = "pim_website" => "Website",
626 PIM_WHEN = "pim_when" => "When",
627 PIM_YOUR_ANSWER = "pim_your_answer" => "Your answer",
628 PROFILE = "profile" => "Profile",
629 PROFILE_SAVE_ERR = "profile_save_err" => "Could not save profile: {}",
630 PROFILE_SAVED = "profile_saved" => "Profile saved",
631 PW_SHORT = "pw_short" => "Password must be at least 8 characters.",
632 READ_ONLY_BADGE = "read_only_badge" => "Read-only",
633 READ_ONLY_HINT = "read_only_hint" => "Read-only folder",
634 REFRESH = "refresh" => "Refresh",
635 REFRESH_FOLDERS = "refresh_folders" => "Refresh your folders",
636 REMOVE_FOLDER = "remove_folder" => "Remove folder",
637 REMOVE_PASSWORD = "remove_password" => "Remove password",
638 REMOVE_PASSWORD_DESC = "remove_password_desc" => "Sign in with passkeys only. Needs at least one passkey.",
639 RENAME = "rename" => "Rename",
640 RENAME_TITLE = "rename_title" => "Rename “{}”",
641 RENAMED = "renamed" => "Renamed",
642 REPEAT_PASSWORD = "repeat_password" => "Repeat password",
643 RETRY = "retry" => "Retry",
644 ROOT_DUP_ERR = "root_dup_err" => "That folder is already in the list.",
645 RW_DISABLED = "rw_disabled" => "Writable shares are disabled by the server.",
646 RW_RO_FOLDER = "rw_ro_folder" => "This folder is read-only, so the share is read-only too.",
647 SAVE = "save" => "Save",
648 SAVE_PROFILE = "save_profile" => "Save profile",
649 SAVE_SETTINGS = "save_settings" => "Save settings",
650 SAVED = "saved" => "Saved",
651 SAVING = "saving" => "Saving…",
652 SEARCH = "search" => "Search",
653 SEARCH_BOTH = "search_both" => "Both",
654 SEARCH_COLLAPSE_ALL = "search_collapse_all" => "Collapse all",
655 SEARCH_CONTENT = "search_content" => "Content",
656 SEARCH_EXCLUDES = "search_excludes" => "Excluded from search",
657 SEARCH_EXCLUDES_EMPTY = "search_excludes_empty" => "No folders are excluded.",
658 SEARCH_EXPAND_ALL = "search_expand_all" => "Expand all",
659 SEARCH_FAILED = "search_failed" => "The search failed.",
660 SEARCH_GOTO = "search_goto" => "Show in folder",
661 SEARCH_HERE = "search_here" => "Search here",
662 SEARCH_IN = "search_in" => "Search in…",
663 SEARCH_IN_FOLDER = "search_in_folder" => "Search in this folder",
664 SEARCH_IN_N_FILES = "search_in_n_files" => "in {} files",
665 SEARCH_N_MATCHES = "search_n_matches" => "{} matches",
666 SEARCH_N_RESULTS = "search_n_results" => "{} results",
667 SEARCH_NAME = "search_name" => "Name",
668 SEARCH_NO_RESULTS = "search_no_results" => "no results",
669 SEARCH_PLACEHOLDER = "search_placeholder" => "Search files and their contents",
670 SEARCH_RUN = "search_run" => "Search",
671 SEARCH_SCANNED = "search_scanned" => "scanned {} files",
672 SEARCH_SHOW_MORE = "search_show_more" => "Show {} more",
673 SEARCH_SHOWN_OF = "search_shown_of" => "Showing {} of {}",
674 SEARCH_SKIPPED = "search_skipped" => "{} skipped (over 10 MiB)",
675 SEARCH_STOP = "search_stop" => "Stop",
676 SEARCH_STOPPED = "search_stopped" => "stopped · {} results",
677 SEARCH_TOOK = "search_took" => "{} ms",
678 SEARCHING = "searching" => "searching…",
679 SECOND_FACTOR_PASSKEY = "second_factor_passkey" => "Now confirm with your passkey.",
680 SECOND_FACTOR_PASSWORD = "second_factor_password" => "Enter the password for {}.",
681 SECURITY = "security" => "Security",
682 SELECT_FOLDER_MSG = "select_folder_msg" => "Choose a folder from the sidebar to start browsing.",
683 SELECT_FOLDER_TITLE = "select_folder_title" => "Select a folder",
684 SERVER = "server" => "Server",
685 SERVER_ROOT = "server_root" => "Server root",
686 SERVER_UNREACHABLE = "server_unreachable" => "The server is not reachable.",
687 SETTINGS = "settings" => "Settings",
688 SETTINGS_SAVE_ERR = "settings_save_err" => "Could not save settings: {}",
689 SETTINGS_SAVED = "settings_saved" => "Settings saved",
690 SETUP_INTRO = "setup_intro" => "First boot: create the admin account. This user can manage other users and server settings.",
691 SETUP_PW_MISMATCH = "setup_pw_mismatch" => "Passwords don't match.",
692 SHARE = "share" => "Share",
693 SHARE_CREATE_ERR = "share_create_err" => "Could not create share: {}",
694 SHARE_DELETE_ERR = "share_delete_err" => "Could not delete share",
695 SHARE_DELETED = "share_deleted" => "Share deleted",
696 SHARE_DIALOG_HINT = "share_dialog_hint" => "Create a link for this item. Writable links let viewers upload and edit.",
697 SHARE_EXPIRED = "share_expired" => "Share expired",
698 SHARE_EXPIRED_MSG = "share_expired_msg" => "This share link is no longer active.",
699 SHARE_LINK = "share_link" => "Share link",
700 SHARE_LOCKED_TITLE = "share_locked_title" => "Password required",
701 SHARE_NOT_FOUND = "share_not_found" => "Share not found",
702 SHARE_NOT_FOUND_MSG = "share_not_found_msg" => "This link is invalid or the share was removed.",
703 SHARE_OWNER_DISABLED = "share_owner_disabled" => "deactivated account",
704 SHARE_PASSWORD_HINT = "share_password_hint" => "Optional. Visitors must enter it before the share opens, at least 8 characters.",
705 SHARE_PERM_RO = "share_perm_ro" => "Anyone with this link can read “{}”.",
706 SHARE_PERM_RW = "share_perm_rw" => "Anyone with this link can read and write “{}”.",
707 SHARE_PROTECTED = "share_protected" => "Password protected",
708 SHARE_TITLE = "share_title" => "Share {}",
709 SHARES = "shares" => "Shares",
710 SHARES_DELETE_ERR = "shares_delete_err" => "Could not delete shares",
711 SHARES_EMPTY_HINT = "shares_empty_hint" => "Right-click a file or folder and choose “Share” to create a link.",
712 SHARES_VIEW_HINT = "shares_view_hint" => "Links you created. Right-click a file or folder and choose “Share” to add one.",
713 SIGN_IN = "sign_in" => "Sign in",
714 SIGNIN_BOTH = "signin_both" => "Password and passkey",
715 SIGNIN_BOTH_DESC = "signin_both_desc" => "Both are required. WebDAV then needs an app password, because a mount can only send a password.",
716 SIGNIN_EITHER = "signin_either" => "Password or passkey",
717 SIGNIN_EITHER_DESC = "signin_either_desc" => "Either one on its own signs you in.",
718 SIGNIN_REQUIREMENT = "signin_requirement" => "Sign-in requirement",
719 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.",
720 SINGLE_CLICK_LABEL = "single_click_label" => "Use single click to open",
721 SIZE = "size" => "Size",
722 SOME_FILES_EXIST = "some_files_exist" => "Some files already exist",
723 SORT_ASC = "sort_asc" => "Ascending",
724 SORT_BY = "sort_by" => "Sort by",
725 SORT_DESC = "sort_desc" => "Descending",
726 THEME_AUTO = "theme_auto" => "Auto",
727 THEME_DARK = "theme_dark" => "Dark",
728 THEME_LIGHT = "theme_light" => "Light",
729 THEME_TITLE = "theme_title" => "Theme: {} (click to switch)",
730 THUMBNAILS_DESC = "thumbnails_desc" => "Show a small preview instead of an icon for images and videos in grid view.",
731 THUMBNAILS_LABEL = "thumbnails_label" => "Show thumbnails",
732 TYPE = "type" => "Type",
733 UNLOCK = "unlock" => "Open share",
734 UNSAVED_CHANGES = "unsaved_changes" => "Unsaved changes",
735 UNTIL = "until" => "Until",
736 UPLOAD_ABORT = "upload_abort" => "Abort",
737 UPLOAD_ABORTED = "upload_aborted" => "Aborted",
738 UPLOAD_ACTIVE_N = "upload_active_n" => "{} active",
739 UPLOAD_APPLY_ALL = "upload_apply_all" => "Apply to files that appear during the upload",
740 UPLOAD_CHECK_FAILED = "upload_check_failed" => "Could not check for existing files: {}",
741 UPLOAD_CLEAR = "upload_clear" => "Remove from list",
742 UPLOAD_CLEAR_FINISHED = "upload_clear_finished" => "Clear finished",
743 UPLOAD_COLLAPSE = "upload_collapse" => "Collapse",
744 UPLOAD_COMPLETE = "upload_complete" => "Upload complete",
745 UPLOAD_CONFLICT_QUESTION = "upload_conflict_question" => "The following files already exist. Overwrite or skip them?",
746 UPLOAD_DROP_HINT = "upload_drop_hint" => "Drop to upload here",
747 UPLOAD_ERRORS_N = "upload_errors_n" => "{} failed",
748 UPLOAD_EXISTS_ASK = "upload_exists_ask" => "“{}” appeared on the server during the upload.",
749 UPLOAD_EXPAND = "upload_expand" => "Expand",
750 UPLOAD_FAILED = "upload_failed" => "Failed",
751 UPLOAD_FILES = "upload_files" => "Upload files",
752 UPLOAD_FOLDER = "upload_folder" => "Upload folder",
753 UPLOAD_N_FILES = "upload_n_files" => "{} files",
754 UPLOAD_PAUSE = "upload_pause" => "Pause",
755 UPLOAD_PAUSED = "upload_paused" => "Paused",
756 UPLOAD_PREPARING = "upload_preparing" => "Preparing…",
757 UPLOAD_RESUME = "upload_resume" => "Resume",
758 UPLOAD_SHOW_GRAPH = "upload_show_graph" => "Details and speed graph",
759 UPLOAD_SKIP = "upload_skip" => "Skip",
760 UPLOAD_SKIPPED_N = "upload_skipped_n" => "{} skipped",
761 UPLOAD_SPEED = "upload_speed" => "{}/s",
762 UPLOAD_WAITING = "upload_waiting" => "Waiting for your answer",
763 UPLOADS = "uploads" => "Uploads",
764 UPLOADS_EMPTY = "uploads_empty" => "No uploads yet",
765 USE_PASSKEY = "use_passkey" => "Use a passkey",
766 USE_PASSKEY_HINT = "use_passkey_hint" => "Leave the name empty unless your passkey needs it.",
767 USER_CREATED = "user_created" => "User created",
768 USER_DELETE_ERR = "user_delete_err" => "Could not delete user",
769 USER_DISABLED = "user_disabled" => "disabled",
770 USER_NAME_EXAMPLE = "user_name_example" => "e.g. alice",
771 USER_SAVE_ERR = "user_save_err" => "Could not save user: {}",
772 USER_UPDATED = "user_updated" => "User updated",
773 USER_YOU = "user_you" => "(you)",
774 USERS = "users" => "Users",
775 WEEK_MONDAY = "week_monday" => "Monday",
776 WEEK_SATURDAY = "week_saturday" => "Saturday",
777 WEEK_START = "week_start" => "Week starts on",
778 WEEK_START_DESC = "week_start_desc" => "The first day of the week in the calendar.",
779 WEEK_SUNDAY = "week_sunday" => "Sunday",
780 YOUR_SHARES = "your_shares" => "Your shares",
781}
782
783/// German translations.
784const DE: &[(&str, &str)] = &[
785 ("active_can_signin", "Aktiv (kann sich anmelden)"),
786 ("add_app_password", "App-Passwort erstellen"),
787 ("add_folder", "Ordner hinzufügen…"),
788 ("add_here", "Diesen Ordner hinzufügen"),
789 ("add_passkey", "Passkey hinzufügen"),
790 ("administrator", "Administrator"),
791 ("all_shares", "Alle Freigaben"),
792 (
793 "all_shares_hint",
794 "Jeder Link auf diesem Server, gruppiert nach dem Konto, das ihn erstellt hat.",
795 ),
796 ("allow_editing", "Bearbeitung erlauben (lesen/schreiben)"),
797 ("allow_rw_shares", "Schreibbare Freigaben erlauben"),
798 (
799 "allow_rw_shares_desc",
800 "Benutzern erlauben, schreibbare Freigabelinks zu erstellen. Standardmäßig aus.",
801 ),
802 ("and_more", "…und {} weitere"),
803 ("app_password_label", "Name für dieses App-Passwort"),
804 ("app_password_removed", "App-Passwort widerrufen"),
805 (
806 "app_password_secret_once",
807 "Jetzt kopieren. Es wird nie wieder angezeigt.",
808 ),
809 ("app_passwords", "App-Passwörter"),
810 (
811 "app_passwords_hint",
812 "Ein App-Passwort gilt nur für WebDAV, nicht für diese Seite. Nutze pro Client eines statt deines Kontopassworts.",
813 ),
814 ("cancel", "Abbrechen"),
815 ("cant_delete_self", "Sie können sich nicht selbst löschen"),
816 ("close", "Schließen"),
817 ("close_esc", "Schließen (Esc)"),
818 ("copied", "Kopiert"),
819 ("copy", "Kopieren"),
820 ("copy_dav_link", "WebDAV-Link kopieren"),
821 ("copy_here", "Hierher kopieren"),
822 ("copy_link", "Link kopieren"),
823 ("copy_manual", "Link manuell kopieren"),
824 ("copy_n_to", "{} Elemente kopieren nach…"),
825 ("copy_to", "„{}“ kopieren nach…"),
826 ("create", "Erstellen"),
827 ("create_admin", "Administrator-Konto erstellen"),
828 ("create_link", "Link erstellen"),
829 ("create_user", "Benutzer erstellen"),
830 ("creating", "Wird erstellt…"),
831 ("ct_type_cell", "mobil"),
832 ("ct_type_fax", "Fax"),
833 ("ct_type_home", "privat"),
834 ("ct_type_other", "andere"),
835 ("ct_type_work", "geschäftlich"),
836 ("custom", "Benutzerdefiniert…"),
837 (
838 "default_root_desc",
839 "Diesen Ordner beim Laden der Seite und über den Home-Link öffnen.",
840 ),
841 ("default_root_label", "Standardordner"),
842 ("default_root_none", "Ordnerübersicht"),
843 ("delete", "Löschen"),
844 ("delete_all", "Alle löschen"),
845 (
846 "delete_all_msg",
847 "Alle {} Freigabelinks löschen? Jeder, der sie besitzt, verliert den Zugriff. Das kann nicht rückgängig gemacht werden.",
848 ),
849 ("delete_all_title", "Alle Freigaben löschen?"),
850 (
851 "delete_all_user_msg",
852 "Alle Freigabelinks von „{}“ löschen? Jeder, der sie besitzt, verliert den Zugriff. Das kann nicht rückgängig gemacht werden.",
853 ),
854 (
855 "delete_folder_msg",
856 "Ordner „{}“ mit allem Inhalt löschen?\nDas kann nicht rückgängig gemacht werden.",
857 ),
858 (
859 "delete_msg",
860 "„{}“ löschen?\nDas kann nicht rückgängig gemacht werden.",
861 ),
862 (
863 "delete_n_msg",
864 "{} Elemente löschen?\nDas kann nicht rückgängig gemacht werden.",
865 ),
866 (
867 "delete_partial",
868 "{} von {} Freigaben konnten nicht gelöscht werden",
869 ),
870 ("delete_share", "Freigabe löschen"),
871 ("delete_user", "Benutzer löschen"),
872 (
873 "delete_user_confirm",
874 "Benutzer „{}“ löschen? Das kann nicht rückgängig gemacht werden.",
875 ),
876 ("deleted", "Gelöscht"),
877 ("deleted_n_shares", "{} Freigabe(n) gelöscht"),
878 ("discard", "Verwerfen"),
879 (
880 "discard_question",
881 "Änderungen verwerfen und den Editor schließen?",
882 ),
883 ("dismiss", "Ausblenden"),
884 ("dismiss_error", "Fehler ausblenden"),
885 ("done", "Fertig"),
886 ("download", "Herunterladen"),
887 (
888 "download_formats_msg",
889 "Archivformat für den Ordner wählen.",
890 ),
891 ("download_started", "Download gestartet"),
892 ("download_title", "„{}“ herunterladen"),
893 ("edit", "Bearbeiten"),
894 ("edit_user_title", "„{}“ bearbeiten"),
895 ("empty_folder", "Dieser Ordner ist leer."),
896 (k::ERR_ADMIN_ONLY, "nur für Administratoren"),
897 (k::ERR_ALREADY_SET_UP, "Server ist bereits eingerichtet"),
898 (
899 k::ERR_APP_PASSWORD_LIMIT,
900 "Dieses Konto hat bereits so viele App-Passwörter, wie es haben darf.",
901 ),
902 (k::ERR_APP_PASSWORD_NOT_FOUND, "Kein solches App-Passwort."),
903 (k::ERR_BAD_ACTION, "action=content erwartet"),
904 (k::ERR_BAD_BODY, "ungültiger Anfrageinhalt"),
905 (k::ERR_BAD_EXPIRES_AT, "das Ablaufdatum ist ungültig"),
906 (
907 k::ERR_BAD_FORMAT,
908 "das Format muss eines der folgenden sein: zip, tar, tar.gz, tar.zst",
909 ),
910 (
911 k::ERR_BAD_MULTIPART,
912 "multipart/form-data mit Boundary erwartet",
913 ),
914 (k::ERR_BAD_PART_NAME, "ungültiger Part-Name"),
915 (
916 k::ERR_BAD_POST,
917 "POST erwartet einen Multipart-Upload, eine JSON-Mutation oder ?action=mkdir/create-file",
918 ),
919 (k::ERR_BAD_UPLOAD, "ungültige Upload-Daten"),
920 (k::ERR_BAD_UPLOAD_PATH, "ungültiger Dateipfad im Upload"),
921 (
922 k::ERR_CHALLENGE_EXPIRED,
923 "Das hat zu lange gedauert. Bitte erneut versuchen.",
924 ),
925 (
926 k::ERR_DEFAULT_CALENDAR,
927 "Der Kalender, der Einladungen empfängt, kann nicht gelöscht werden.",
928 ),
929 (k::ERR_DST_REQUIRED, "dst_root_id ist erforderlich"),
930 (k::ERR_FILE_NAME_REQUIRED, "ein Dateiname ist erforderlich"),
931 (k::ERR_FILES_EXIST, "einige Dateien existieren bereits"),
932 (
933 k::ERR_FOLDER_EXISTS,
934 "ein Ordner mit diesem Namen existiert bereits",
935 ),
936 (
937 k::ERR_FOLDER_NAME_REQUIRED,
938 "ein Ordnername ist erforderlich",
939 ),
940 (k::ERR_FS_CONFLICT, "existiert bereits"),
941 (k::ERR_FS_FORBIDDEN, "Zugriff verweigert"),
942 (k::ERR_FS_NOT_A_DIR, "kein Ordner"),
943 (k::ERR_FS_NOT_FOUND, "Ordner nicht gefunden"),
944 (
945 k::ERR_FS_ROOT_MISSING,
946 "der konfigurierte Ordner existiert nicht mehr",
947 ),
948 (k::ERR_INTERNAL, "interner Fehler"),
949 (k::ERR_INVALID_CREDENTIALS, "Name oder Passwort ungültig"),
950 (
951 k::ERR_INVALID_DEFAULT_ROOT,
952 "Der Standardordner gehört nicht zu Ihren Ordnern",
953 ),
954 (k::ERR_INVALID_LANGUAGE, "ungültiges Sprachkürzel"),
955 (k::ERR_INVALID_WEEK_START, "ungültiger Wochenbeginn"),
956 (
957 k::ERR_LAST_ADMIN,
958 "der letzte aktive Administrator kann nicht entfernt werden",
959 ),
960 (
961 k::ERR_LAST_ADMIN_DELETE,
962 "der letzte aktive Administrator kann nicht gelöscht werden",
963 ),
964 (
965 k::ERR_LOCKED_OUT,
966 "Dann hätte das Konto keine Anmeldemöglichkeit mehr.",
967 ),
968 (
969 k::ERR_MODE_NEEDS_PASSKEY,
970 "Fügen Sie einen Passkey hinzu, bevor Sie beides verlangen.",
971 ),
972 (
973 k::ERR_MODE_NEEDS_PASSWORD,
974 "Setzen Sie ein Passwort, bevor Sie beides verlangen.",
975 ),
976 (k::ERR_NAME_LENGTH, "der Name muss 1–64 Zeichen haben"),
977 (k::ERR_NEW_NAME_REQUIRED, "new_name ist erforderlich"),
978 (k::ERR_NO_FILES_UPLOADED, "keine Dateien hochgeladen"),
979 (k::ERR_NO_SUCH_FOLDER, "dieser Ordner existiert nicht"),
980 (k::ERR_NOT_A_FILE, "keine Datei"),
981 (k::ERR_NOT_SIGNED_IN, "nicht angemeldet"),
982 (
983 k::ERR_OWN_ACCOUNT,
984 "Sie können Ihr eigenes Konto nicht deaktivieren",
985 ),
986 (
987 k::ERR_OWN_ADMIN,
988 "Sie können Ihre eigenen Administratorrechte nicht entfernen",
989 ),
990 (
991 k::ERR_OWN_DELETE,
992 "Sie können Ihr eigenes Konto nicht löschen",
993 ),
994 (k::ERR_PART_NO_NAME, "Part ohne Namen"),
995 (
996 k::ERR_PASSKEY_DUPLICATE,
997 "Dieser Passkey ist bereits registriert.",
998 ),
999 (
1000 k::ERR_PASSKEY_FAILED,
1001 "Dieser Passkey konnte nicht verwendet werden.",
1002 ),
1003 (
1004 k::ERR_PASSKEY_LAST_CREDENTIAL,
1005 "Setzen Sie ein Passwort, bevor Sie den letzten Passkey entfernen.",
1006 ),
1007 (
1008 k::ERR_PASSKEY_LIMIT,
1009 "Dieses Konto hat bereits so viele Passkeys wie erlaubt.",
1010 ),
1011 (
1012 k::ERR_PASSKEY_MALFORMED,
1013 "Der Browser hat unlesbare Daten gesendet.",
1014 ),
1015 (k::ERR_PASSKEY_NOT_FOUND, "Passkey nicht gefunden."),
1016 (
1017 k::ERR_PASSKEY_ORIGIN,
1018 "Passkeys sind für eine andere Adresse eingerichtet.",
1019 ),
1020 (
1021 k::ERR_PASSKEY_UNAVAILABLE,
1022 "Passkeys sind hier nicht verfügbar.",
1023 ),
1024 (
1025 k::ERR_PASSWORD_LAST_CREDENTIAL,
1026 "Fügen Sie einen Passkey hinzu, bevor Sie das Passwort entfernen.",
1027 ),
1028 (
1029 k::ERR_PASSWORD_SHORT,
1030 "das Passwort muss mindestens 8 Zeichen lang sein",
1031 ),
1032 (
1033 k::ERR_PATH_REQUIRED,
1034 "ein Pfad innerhalb des Ordners ist erforderlich",
1035 ),
1036 (k::ERR_READ_ONLY_FOLDER, "schreibgeschützter Ordner"),
1037 (
1038 k::ERR_REQUIRED_BY_MODE,
1039 "Dieses Konto verlangt Passwort und Passkey.",
1040 ),
1041 (k::ERR_ROOT_FORBIDDEN, "kein Zugriff auf diesen Ordner"),
1042 (
1043 k::ERR_RW_RO_FOLDER,
1044 "dieser Ordner ist für Sie schreibgeschützt und kann nicht schreibbar freigegeben werden",
1045 ),
1046 (
1047 k::ERR_RW_SHARES_DISABLED,
1048 "schreibbare Freigaben sind deaktiviert",
1049 ),
1050 (
1051 k::ERR_SAVE_FAILED,
1052 "die Datei konnte nicht gespeichert werden",
1053 ),
1054 (
1055 k::ERR_SEARCH_BAD_SCOPE,
1056 "Bereich muss name, content oder both sein",
1057 ),
1058 (
1059 k::ERR_SEARCH_FORBIDDEN,
1060 "Suche erfordert eine angemeldete Sitzung",
1061 ),
1062 (
1063 k::ERR_SESSION_EXPIRED,
1064 "Sitzung abgelaufen, bitte erneut anmelden",
1065 ),
1066 (k::ERR_SHARE_EXPIRED, "diese Freigabe ist abgelaufen"),
1067 (k::ERR_SHARE_LOCKED, "Diese Freigabe ist passwortgeschützt."),
1068 (
1069 k::ERR_SHARE_NO_PASSWORD,
1070 "Diese Freigabe hat kein Passwort.",
1071 ),
1072 (k::ERR_SHARE_NOT_FOUND, "Freigabe nicht gefunden"),
1073 (
1074 k::ERR_SHARE_TOKEN_FORBIDDEN,
1075 "ein Freigabetoken kann hier nicht verwendet werden; bitte anmelden",
1076 ),
1077 (k::ERR_SHARE_WRONG_PASSWORD, "Falsches Passwort."),
1078 (k::ERR_TOO_LARGE_PREVIEW, "Datei zu groß für eine Vorschau"),
1079 (k::ERR_TOO_LARGE_SAVE, "Datei zu groß zum Speichern"),
1080 (
1081 k::ERR_USER_EXISTS,
1082 "ein Benutzer mit diesem Namen existiert bereits",
1083 ),
1084 (k::ERR_USER_NOT_FOUND, "Benutzer nicht gefunden"),
1085 (
1086 "exclude_dup_err",
1087 "Dieser Ordner ist bereits ausgeschlossen.",
1088 ),
1089 ("exclude_folder", "Ordner ausschließen…"),
1090 ("exclude_here", "Diesen Ordner ausschließen"),
1091 (
1092 "exclude_root_err",
1093 "Das gesamte Stammverzeichnis kann nicht ausgeschlossen werden; das würde die Suche abschalten.",
1094 ),
1095 ("expires", "Läuft ab"),
1096 ("expires_at", "Läuft ab: {}"),
1097 ("expiry_1d", "1 Tag"),
1098 ("expiry_1h", "1 Stunde"),
1099 ("expiry_1mo", "1 Monat"),
1100 ("expiry_1w", "1 Woche"),
1101 ("file", "Datei"),
1102 ("file_changed", "Datei auf der Festplatte geändert"),
1103 ("file_created", "Datei erstellt"),
1104 ("file_info", "Datei-Info"),
1105 ("file_name", "Dateiname"),
1106 ("file_not_found", "Datei nicht gefunden"),
1107 ("files", "Dateien"),
1108 ("fmt_tar", "Tar"),
1109 ("fmt_targz", "Tar + gzip"),
1110 ("fmt_tarzst", "Tar + zstd"),
1111 ("fmt_zip", "Zip"),
1112 ("folder", "Ordner"),
1113 ("folder_created", "Ordner erstellt"),
1114 (
1115 "folder_gone_msg",
1116 "Dieser Ordner ist nicht mehr verfügbar. Wählen Sie links einen anderen aus.",
1117 ),
1118 ("folder_gone_title", "Ordner nicht verfügbar"),
1119 ("folder_name", "Ordnername"),
1120 ("folders", "Ordner"),
1121 (
1122 "folders_paths_hint",
1123 "Pfade sind relativ zur Serverwurzel. „.“ ist der gesamte Wurzelordner.",
1124 ),
1125 ("grid_view", "Kachelansicht"),
1126 ("info", "Info"),
1127 ("keep_editing", "Weiter bearbeiten"),
1128 ("lang_auto", "Automatisch"),
1129 ("lang_de", "Deutsch"),
1130 ("lang_en", "Englisch"),
1131 ("lang_fr", "Französisch"),
1132 ("language", "Sprache"),
1133 (
1134 "language_desc",
1135 "Die Sprache der Benutzeroberfläche. „Automatisch“ verwendet die Sprache Ihres Browsers.",
1136 ),
1137 ("link_copied", "Link in die Zwischenablage kopiert"),
1138 ("list_view", "Listenansicht"),
1139 ("load_latest", "Neueste Version laden"),
1140 ("loading", "Wird geladen…"),
1141 ("loading_share", "Freigabe wird geladen…"),
1142 ("location", "Ort"),
1143 ("log_out", "Abmelden"),
1144 ("login_subtitle", "Anmelden, um fortzufahren."),
1145 ("manage", "Verwalten"),
1146 ("menu", "Menü"),
1147 ("meta_created", "erstellt: {}"),
1148 ("meta_expires", "läuft ab: {}"),
1149 ("mode_ro", "nur lesen"),
1150 ("mode_rw", "lesen/schreiben"),
1151 ("modified", "Geändert"),
1152 (
1153 "modified_after",
1154 "Diese Datei wurde nach dem Öffnen geändert. „Neueste Version laden“ verwirft Ihre ungespeicherten Änderungen; „Überschreiben“ behält Ihre Version bei.",
1155 ),
1156 ("more_actions", "Weitere Aktionen"),
1157 ("move", "Verschieben"),
1158 ("move_here", "Hierher verschieben"),
1159 ("move_n_to", "{} Elemente verschieben nach…"),
1160 ("move_to", "„{}“ verschieben nach…"),
1161 ("moved", "Verschoben"),
1162 ("name", "Name"),
1163 ("name_taken", "Name wird bereits verwendet"),
1164 (
1165 "need_folder",
1166 "Dem Benutzer muss mindestens ein Ordner zugewiesen werden.",
1167 ),
1168 ("never", "Nie"),
1169 ("never_expires", "Läuft nie ab"),
1170 ("new_file", "Neue Datei"),
1171 ("new_folder", "Neuer Ordner"),
1172 ("new_name", "Neuer Name"),
1173 ("new_password", "Neues Passwort"),
1174 (
1175 "new_password_hint",
1176 "Leer lassen, um das aktuelle Passwort zu behalten.",
1177 ),
1178 (
1179 "new_password_keep",
1180 "Neues Passwort (leer lassen, um beizubehalten)",
1181 ),
1182 ("new_user", "Neuer Benutzer"),
1183 ("no_app_passwords", "Keine App-Passwörter."),
1184 (
1185 "no_folders_msg",
1186 "Ein Administrator hat Ihnen noch keine Ordner zugewiesen.",
1187 ),
1188 ("no_folders_title", "Keine Ordner verfügbar"),
1189 ("no_passkeys", "Noch keine Passkeys."),
1190 (
1191 "no_password_set",
1192 "Dieses Konto meldet sich nur mit Passkeys an.",
1193 ),
1194 ("no_preview", "Keine Vorschau verfügbar"),
1195 ("no_preview_msg", "Die App kann „{}“ hier nicht anzeigen."),
1196 ("no_shares", "Noch keine Freigaben"),
1197 ("no_subfolders", "Keine Unterordner"),
1198 ("no_users", "Keine Benutzer."),
1199 ("open", "Öffnen"),
1200 ("open_in_new_tab", "In neuem Tab öffnen"),
1201 ("open_menu", "Menü öffnen"),
1202 ("or_label", "oder"),
1203 ("overwrite", "Überschreiben"),
1204 (
1205 "overwrite_question",
1206 "Die folgenden Dateien existieren bereits. Überschreiben?",
1207 ),
1208 ("page_first", "Erste Seite"),
1209 ("page_goto", "Seite"),
1210 ("page_last", "Letzte Seite"),
1211 ("page_next", "Nächste Seite"),
1212 ("page_prev", "Vorherige Seite"),
1213 ("page_size", "Einträge pro Seite"),
1214 ("page_size_n", "{} pro Seite"),
1215 ("passkey_added", "Passkey hinzugefügt"),
1216 ("passkey_added_on", "Hinzugefügt {}"),
1217 ("passkey_label", "Name für diesen Passkey"),
1218 ("passkey_last_used", "Zuletzt benutzt {}"),
1219 ("passkey_needs_name", "Braucht Ihren Benutzernamen"),
1220 (
1221 "passkey_needs_name_hint",
1222 "Dieser Passkey liegt nicht im Authenticator selbst, der Server muss ihn nachschlagen. Geben Sie Ihren Benutzernamen auf der Anmeldeseite ein, bevor Sie ihn verwenden.",
1223 ),
1224 ("passkey_never_used", "Nie benutzt"),
1225 ("passkey_not_used", "Es wurde kein Passkey verwendet."),
1226 ("passkey_removed", "Passkey entfernt"),
1227 (
1228 "passkey_unsupported",
1229 "Dieser Browser kann keine Passkeys verwenden.",
1230 ),
1231 ("passkeys", "Passkeys"),
1232 (
1233 "passkeys_hint",
1234 "Ein Passkey meldet Sie mit Fingerabdruck, Gesicht oder Sicherheitsschlüssel an.",
1235 ),
1236 ("password", "Passwort"),
1237 ("password_min_hint", "mindestens 8 Zeichen"),
1238 ("password_removed", "Passwort entfernt"),
1239 (
1240 "password_resets_signin",
1241 "Ein neues Passwort löscht auch die Passkeys dieses Kontos und hebt eine Zwei-Faktor-Pflicht auf.",
1242 ),
1243 ("pim_accept", "Zusagen"),
1244 ("pim_access", "Zugriff"),
1245 ("pim_add", "Hinzufügen"),
1246 ("pim_address", "Adresse für Apps"),
1247 ("pim_address_book", "Adressbuch"),
1248 ("pim_address_books", "Adressbücher"),
1249 ("pim_agenda", "Liste"),
1250 ("pim_all_day", "Ganztägig"),
1251 ("pim_all_events", "Alle Termine der Serie"),
1252 ("pim_anniversary", "Jahrestag"),
1253 ("pim_app_passwords", "App-Passwort erstellen"),
1254 ("pim_attendees", "Teilnehmer"),
1255 ("pim_auto", "automatisch"),
1256 ("pim_back", "Zurück"),
1257 ("pim_birthday", "Geburtstag"),
1258 ("pim_birthdays", "Geburtstage"),
1259 ("pim_calendar", "Kalender"),
1260 ("pim_calendars", "Kalender"),
1261 ("pim_cancelled", "Abgesagt"),
1262 ("pim_categories", "Kategorien"),
1263 ("pim_clients", "Apps"),
1264 (
1265 "pim_collection_urls",
1266 "Adressen einzelner Kalender und Adressbücher",
1267 ),
1268 ("pim_color", "Farbe"),
1269 ("pim_connect", "App verbinden"),
1270 ("pim_connect_title", "Kalender- oder Kontakte-App verbinden"),
1271 ("pim_contacts", "Kontakte"),
1272 ("pim_created", "Erstellt"),
1273 ("pim_custom_color", "Eigene Farbe"),
1274 ("pim_decline", "Absagen"),
1275 (
1276 "pim_default_hint",
1277 "Dieser Kalender empfängt Einladungen. Er kann nicht gelöscht werden.",
1278 ),
1279 (
1280 "pim_delete_msg",
1281 "Alles darin wird gelöscht. Die Teilnehmer Ihrer Termine erhalten eine Absage.",
1282 ),
1283 ("pim_delete_title", "„{}“ löschen?"),
1284 ("pim_description", "Beschreibung"),
1285 ("pim_detail", "Details"),
1286 ("pim_detail_busy", "Nur belegte Zeiten"),
1287 ("pim_detail_full", "Alle Details"),
1288 ("pim_directory", "Verzeichnis"),
1289 ("pim_email", "E-Mail"),
1290 ("pim_events_n", "{} Termine"),
1291 ("pim_events_one", "1 Termin"),
1292 ("pim_export", "Exportieren"),
1293 ("pim_feeds_of", "Feeds von {}"),
1294 ("pim_file", "Datei"),
1295 ("pim_from_organizer", "Von {}"),
1296 ("pim_from_time", "ab {}"),
1297 ("pim_general", "Allgemein"),
1298 (
1299 "pim_generated_hint",
1300 "Der Server füllt dies aus. Es ist schreibgeschützt.",
1301 ),
1302 ("pim_group", "Gruppe"),
1303 ("pim_hide", "Ausblenden"),
1304 (
1305 "pim_hint_apple",
1306 "Apple: Fügen Sie ein CalDAV- und ein CardDAV-Konto mit der Serveradresse hinzu. Apple braucht HTTPS.",
1307 ),
1308 (
1309 "pim_hint_davx5",
1310 "Android: Melden Sie sich in DAVx⁵ mit URL und Benutzername an und nutzen Sie die Serveradresse.",
1311 ),
1312 (
1313 "pim_hint_gnome",
1314 "GNOME und Evolution: Fügen Sie ein CalDAV- oder WebDAV-Konto mit der Serveradresse hinzu.",
1315 ),
1316 (
1317 "pim_hint_thunderbird",
1318 "Thunderbird: Fügen Sie einen Netzwerkkalender mit der Serveradresse hinzu. Setzen Sie seine E-Mail-Identität auf „Keine“, sonst verschickt er keine Einladungen.",
1319 ),
1320 ("pim_import", "Importieren"),
1321 ("pim_import_done", "{} neu, {} aktualisiert."),
1322 ("pim_import_file", "Datei importieren…"),
1323 (
1324 "pim_import_hint_cal",
1325 "Fügt die Termine einer .ics-Datei zu diesem Kalender hinzu. Ein Termin, der schon da ist, wird aktualisiert.",
1326 ),
1327 (
1328 "pim_import_hint_cards",
1329 "Fügt die Kontakte einer .vcf-Datei zu diesem Adressbuch hinzu. Ein Kontakt, der schon da ist, wird aktualisiert.",
1330 ),
1331 (
1332 "pim_import_new_hint_cal",
1333 "Legt einen Kalender mit den Terminen einer .ics-Datei an.",
1334 ),
1335 (
1336 "pim_import_new_hint_cards",
1337 "Legt ein Adressbuch mit den Kontakten einer .vcf-Datei an.",
1338 ),
1339 (
1340 "pim_import_nothing",
1341 "Nichts ließ sich importieren, daher wurde nichts angelegt.",
1342 ),
1343 ("pim_import_skipped", "{} übersprungen:"),
1344 ("pim_imported_as", "Importiert als „{}“."),
1345 ("pim_importing", "Importiere…"),
1346 (
1347 "pim_inv_series_hint",
1348 "Ihre Antwort gilt für die ganze Serie.",
1349 ),
1350 ("pim_invitations", "Einladungen"),
1351 ("pim_kind_resource", "Ressource"),
1352 ("pim_kind_room", "Raum"),
1353 ("pim_link", "Link"),
1354 ("pim_link_busy", "nur belegte Zeiten"),
1355 ("pim_link_full", "alle Details"),
1356 ("pim_link_revoked", "Link widerrufen"),
1357 ("pim_links", "Öffentliche Links"),
1358 (
1359 "pim_links_hint",
1360 "Jeder mit dem Link kann ihn abonnieren. Manche Kalender, z. B. Google Kalender und Outlook.com, brauchen einen Link ohne Passwort.",
1361 ),
1362 (
1363 "pim_links_hint_cards",
1364 "Jeder mit dem Link kann die Kontakte einmal herunterladen. Apps folgen keinen Änderungen.",
1365 ),
1366 ("pim_location", "Ort"),
1367 ("pim_manage", "Einstellungen"),
1368 ("pim_manage_of", "Einstellungen für {}"),
1369 ("pim_members", "Mitglieder"),
1370 ("pim_mode_ro", "Nur lesen"),
1371 ("pim_mode_rw", "Lesen und schreiben"),
1372 (
1373 "pim_mode_schedule",
1374 "Lesen, schreiben und Einladungen senden",
1375 ),
1376 ("pim_month", "Monat"),
1377 ("pim_more_n", "+{} weitere"),
1378 ("pim_name_from_file", "Aus der Datei, wenn leer"),
1379 ("pim_nav", "Kalender & Kontakte"),
1380 ("pim_new_address_book", "Neues Adressbuch"),
1381 ("pim_new_book_from_file", "Neues Adressbuch aus Datei"),
1382 ("pim_new_calendar", "Neuer Kalender"),
1383 ("pim_new_calendar_from_file", "Neuer Kalender aus Datei"),
1384 ("pim_new_from_file", "Neu aus Datei…"),
1385 ("pim_new_room", "Neuer Raum"),
1386 ("pim_next_month", "Nächster Monat"),
1387 (
1388 "pim_no_contacts",
1389 "Noch keine Kontakte. Fügen Sie welche mit einer Kontakte-App oder einem Import hinzu.",
1390 ),
1391 (
1392 "pim_no_events_agenda",
1393 "Keine Termine in den nächsten 7 Tagen.",
1394 ),
1395 ("pim_no_events_day", "Keine Termine an diesem Tag."),
1396 ("pim_no_invitations", "Keine offenen Einladungen."),
1397 ("pim_no_links", "Keine öffentlichen Links."),
1398 ("pim_no_match", "Kein Kontakt passt."),
1399 ("pim_no_rooms", "Keine Räume oder Ressourcen."),
1400 ("pim_no_shares", "Mit niemandem geteilt."),
1401 ("pim_no_title", "(ohne Titel)"),
1402 ("pim_not_contact", "Dieser Eintrag ist kein Kontakt."),
1403 ("pim_not_event", "Dieser Eintrag ist kein Termin."),
1404 ("pim_note", "Notiz"),
1405 ("pim_optional", "optional"),
1406 ("pim_organizer", "Organisator"),
1407 (
1408 "pim_own_empty",
1409 "Keine öffentlichen Links und nichts mit anderen Benutzern geteilt.",
1410 ),
1411 (
1412 "pim_own_hint",
1413 "Öffentliche Links zu Ihren Kalendern und Adressbüchern und was Sie mit anderen Benutzern teilen. Sie lassen sich auch in den Einstellungen der Sammlung verwalten.",
1414 ),
1415 ("pim_own_lends", "Mit anderen Benutzern geteilt"),
1416 ("pim_own_links", "Ihre öffentlichen Links"),
1417 (
1418 "pim_password_hint",
1419 "Nutzen Sie ein App-Passwort statt Ihres Kontopassworts.",
1420 ),
1421 ("pim_phone", "Telefon"),
1422 (
1423 "pim_pick_contact",
1424 "Wählen Sie einen Kontakt, um die Details zu sehen.",
1425 ),
1426 ("pim_postal", "Adresse"),
1427 ("pim_prev_month", "Vorheriger Monat"),
1428 ("pim_ps_accepted", "Zugesagt"),
1429 ("pim_ps_declined", "Abgesagt"),
1430 ("pim_ps_delegated", "Delegiert"),
1431 ("pim_ps_needs_action", "Noch keine Antwort"),
1432 ("pim_ps_tentative", "Vielleicht"),
1433 ("pim_receives_invitations", "Empfängt Einladungen"),
1434 ("pim_remove_from_list", "Aus meiner Liste entfernen"),
1435 (
1436 "pim_remove_msg",
1437 "Sie sehen ihn nicht mehr. Der Eigentümer kann ihn erneut teilen.",
1438 ),
1439 ("pim_removed", "Aus Ihrer Liste entfernt"),
1440 ("pim_repeats", "Wiederholung"),
1441 ("pim_replied", "Antwort gesendet"),
1442 (
1443 "pim_room_delete_confirm",
1444 "„{}“ löschen? Seine Buchungen gehen verloren.",
1445 ),
1446 ("pim_room_display", "Anzeigename"),
1447 ("pim_room_name", "Name (Teil der Adresse, nicht änderbar)"),
1448 ("pim_rooms", "Räume und Ressourcen"),
1449 (
1450 "pim_rooms_hint",
1451 "Räume und Ressourcen können zu Terminen eingeladen werden. Sie nehmen freie Zeiten an und lehnen belegte selbst ab.",
1452 ),
1453 ("pim_rrule_count", "{}-mal"),
1454 ("pim_rrule_daily", "Jeden Tag"),
1455 ("pim_rrule_daily_n", "Alle {} Tage"),
1456 ("pim_rrule_last_day", "letzter Tag"),
1457 ("pim_rrule_month_day", "am {}."),
1458 ("pim_rrule_monthly", "Jeden Monat"),
1459 ("pim_rrule_monthly_n", "Alle {} Monate"),
1460 ("pim_rrule_nth", "{} {}"),
1461 ("pim_rrule_ord_1", "1."),
1462 ("pim_rrule_ord_2", "2."),
1463 ("pim_rrule_ord_3", "3."),
1464 ("pim_rrule_ord_4", "4."),
1465 ("pim_rrule_ord_5", "5."),
1466 ("pim_rrule_ord_last", "letzter"),
1467 ("pim_rrule_until", "bis {}"),
1468 ("pim_rrule_weekly", "Jede Woche"),
1469 ("pim_rrule_weekly_n", "Alle {} Wochen"),
1470 ("pim_rrule_yearly", "Jedes Jahr"),
1471 ("pim_rrule_yearly_n", "Alle {} Jahre"),
1472 ("pim_save_err", "Speichern fehlgeschlagen: {}"),
1473 ("pim_search_contacts", "Kontakte suchen"),
1474 ("pim_server_address", "Serveradresse"),
1475 (
1476 "pim_server_address_hint",
1477 "Wenn eine App den Server nicht findet, nutzen Sie diese Adresse:",
1478 ),
1479 ("pim_shared_by", "Geteilt von {}"),
1480 ("pim_shared_ok", "Geteilt mit {}"),
1481 ("pim_shared_with_me", "Mit mir geteilt"),
1482 ("pim_sharing", "Teilen"),
1483 (
1484 "pim_sharing_hint",
1485 "Mit einem anderen Konto auf diesem Server teilen.",
1486 ),
1487 ("pim_show", "Einblenden"),
1488 ("pim_show_all", "Alle anzeigen"),
1489 ("pim_show_only", "Nur diesen Eintrag anzeigen"),
1490 (
1491 "pim_skip_component",
1492 "dieser Typ wird hier nicht angenommen",
1493 ),
1494 ("pim_skip_invalid", "ungültige oder unvollständige Daten"),
1495 ("pim_skip_size", "zu groß"),
1496 (
1497 "pim_skip_uid",
1498 "dieselbe UID liegt schon in einem anderen Kalender",
1499 ),
1500 ("pim_subscribe", "Abonnieren"),
1501 ("pim_tentative", "Vielleicht"),
1502 ("pim_this_event", "Nur dieser Termin"),
1503 ("pim_today", "Heute"),
1504 (
1505 "pim_transparent",
1506 "Als frei anzeigen: Termine blockieren bei Einladungen keine Zeitfenster",
1507 ),
1508 (
1509 "pim_truncated",
1510 "Nicht alle Termine passen in diese Ansicht. Blenden Sie Kalender aus, um den Rest zu sehen.",
1511 ),
1512 ("pim_unshare", "Nicht mehr teilen"),
1513 ("pim_unshared", "Nicht mehr geteilt"),
1514 ("pim_until_time", "bis {}"),
1515 ("pim_upcoming", "Nächste 7 Tage"),
1516 ("pim_user", "Benutzername"),
1517 ("pim_user_name", "Benutzername"),
1518 ("pim_website", "Webseite"),
1519 ("pim_when", "Wann"),
1520 ("pim_your_answer", "Ihre Antwort"),
1521 ("profile", "Profil"),
1522 (
1523 "profile_save_err",
1524 "Profil konnte nicht gespeichert werden: {}",
1525 ),
1526 ("profile_saved", "Profil gespeichert"),
1527 (
1528 "pw_short",
1529 "Das Passwort muss mindestens 8 Zeichen lang sein.",
1530 ),
1531 ("read_only_badge", "Schreibgeschützt"),
1532 ("read_only_hint", "Schreibgeschützter Ordner"),
1533 ("refresh", "Aktualisieren"),
1534 ("refresh_folders", "Ordner aktualisieren"),
1535 ("remove_folder", "Ordner entfernen"),
1536 ("remove_password", "Passwort entfernen"),
1537 (
1538 "remove_password_desc",
1539 "Nur noch mit Passkeys anmelden. Braucht mindestens einen Passkey.",
1540 ),
1541 ("rename", "Umbenennen"),
1542 ("rename_title", "„{}“ umbenennen"),
1543 ("renamed", "Umbenannt"),
1544 ("repeat_password", "Passwort wiederholen"),
1545 ("retry", "Erneut versuchen"),
1546 ("root_dup_err", "Dieser Ordner ist bereits in der Liste."),
1547 (
1548 "rw_disabled",
1549 "Schreibbare Freigaben sind vom Server deaktiviert.",
1550 ),
1551 (
1552 "rw_ro_folder",
1553 "Dieser Ordner ist schreibgeschützt, daher ist die Freigabe auch schreibgeschützt.",
1554 ),
1555 ("save", "Speichern"),
1556 ("save_profile", "Profil speichern"),
1557 ("save_settings", "Einstellungen speichern"),
1558 ("saved", "Gespeichert"),
1559 ("saving", "Wird gespeichert…"),
1560 ("search", "Suche"),
1561 ("search_both", "Beides"),
1562 ("search_collapse_all", "Alle einklappen"),
1563 ("search_content", "Inhalt"),
1564 ("search_excludes", "Von der Suche ausgeschlossen"),
1565 ("search_excludes_empty", "Keine Ordner ausgeschlossen."),
1566 ("search_expand_all", "Alle ausklappen"),
1567 ("search_failed", "Die Suche ist fehlgeschlagen."),
1568 ("search_goto", "Im Ordner anzeigen"),
1569 ("search_here", "Hier suchen"),
1570 ("search_in", "Suchen in…"),
1571 ("search_in_folder", "In diesem Ordner suchen"),
1572 ("search_in_n_files", "in {} Dateien"),
1573 ("search_n_matches", "{} Treffer"),
1574 ("search_n_results", "{} Treffer"),
1575 ("search_name", "Name"),
1576 ("search_no_results", "keine Treffer"),
1577 (
1578 "search_placeholder",
1579 "Dateien und deren Inhalte durchsuchen",
1580 ),
1581 ("search_run", "Suchen"),
1582 ("search_scanned", "{} Dateien durchsucht"),
1583 ("search_show_more", "{} weitere anzeigen"),
1584 ("search_shown_of", "{} von {} angezeigt"),
1585 ("search_skipped", "{} übersprungen (über 10 MiB)"),
1586 ("search_stop", "Stopp"),
1587 ("search_stopped", "gestoppt · {} Treffer"),
1588 ("search_took", "{} ms"),
1589 ("searching", "Suche läuft…"),
1590 (
1591 "second_factor_passkey",
1592 "Bestätigen Sie jetzt mit Ihrem Passkey.",
1593 ),
1594 ("second_factor_password", "Passwort für {} eingeben."),
1595 ("security", "Sicherheit"),
1596 (
1597 "select_folder_msg",
1598 "Wählen Sie links einen Ordner aus, um mit dem Durchsuchen zu beginnen.",
1599 ),
1600 ("select_folder_title", "Ordner auswählen"),
1601 ("server", "Server"),
1602 ("server_root", "Serverwurzel"),
1603 ("server_unreachable", "Der Server ist nicht erreichbar."),
1604 ("settings", "Einstellungen"),
1605 (
1606 "settings_save_err",
1607 "Einstellungen konnten nicht gespeichert werden: {}",
1608 ),
1609 ("settings_saved", "Einstellungen gespeichert"),
1610 (
1611 "setup_intro",
1612 "Erster Start: Erstellen Sie das Administrator-Konto. Dieser Benutzer kann andere Benutzer und die Servereinstellungen verwalten.",
1613 ),
1614 ("setup_pw_mismatch", "Die Passwörter stimmen nicht überein."),
1615 ("share", "Teilen"),
1616 (
1617 "share_create_err",
1618 "Freigabe konnte nicht erstellt werden: {}",
1619 ),
1620 ("share_delete_err", "Freigabe konnte nicht gelöscht werden"),
1621 ("share_deleted", "Freigabe gelöscht"),
1622 (
1623 "share_dialog_hint",
1624 "Erstellt einen Link für diesen Eintrag. Mit schreibbaren Links können Empfänger Dateien hochladen und bearbeiten.",
1625 ),
1626 ("share_expired", "Freigabe abgelaufen"),
1627 (
1628 "share_expired_msg",
1629 "Dieser Freigabelink ist nicht mehr aktiv.",
1630 ),
1631 ("share_link", "Freigabelink"),
1632 ("share_locked_title", "Passwort erforderlich"),
1633 ("share_not_found", "Freigabe nicht gefunden"),
1634 (
1635 "share_not_found_msg",
1636 "Dieser Link ist ungültig oder die Freigabe wurde entfernt.",
1637 ),
1638 ("share_owner_disabled", "deaktiviertes Konto"),
1639 (
1640 "share_password_hint",
1641 "Optional. Besucher müssen es eingeben, bevor die Freigabe geöffnet wird, mindestens 8 Zeichen.",
1642 ),
1643 ("share_perm_ro", "Jeder mit diesem Link kann „{}“ lesen."),
1644 (
1645 "share_perm_rw",
1646 "Jeder mit diesem Link kann „{}“ lesen und schreiben.",
1647 ),
1648 ("share_protected", "Passwortgeschützt"),
1649 ("share_title", "{} teilen"),
1650 ("shares", "Freigaben"),
1651 (
1652 "shares_delete_err",
1653 "Freigaben konnten nicht gelöscht werden",
1654 ),
1655 (
1656 "shares_empty_hint",
1657 "Klicken Sie mit der rechten Maustaste auf eine Datei oder einen Ordner und wählen Sie „Teilen“, um einen Link zu erstellen.",
1658 ),
1659 (
1660 "shares_view_hint",
1661 "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.",
1662 ),
1663 ("sign_in", "Anmelden"),
1664 ("signin_both", "Passwort und Passkey"),
1665 (
1666 "signin_both_desc",
1667 "Beides ist nötig. WebDAV braucht dann ein App-Passwort, weil eine Einbindung nur ein Passwort senden kann.",
1668 ),
1669 ("signin_either", "Passwort oder Passkey"),
1670 (
1671 "signin_either_desc",
1672 "Eines davon allein genügt zur Anmeldung.",
1673 ),
1674 ("signin_requirement", "Anmeldung verlangt"),
1675 (
1676 "single_click_desc",
1677 "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.",
1678 ),
1679 ("single_click_label", "Einzelklick öffnet Einträge"),
1680 ("size", "Größe"),
1681 ("some_files_exist", "Einige Dateien existieren bereits"),
1682 ("sort_asc", "Aufsteigend"),
1683 ("sort_by", "Sortieren nach"),
1684 ("sort_desc", "Absteigend"),
1685 ("theme_auto", "Auto"),
1686 ("theme_dark", "Dunkel"),
1687 ("theme_light", "Hell"),
1688 ("theme_title", "Design: {} (klicken zum Wechseln)"),
1689 (
1690 "thumbnails_desc",
1691 "Für Bilder und Videos in der Kachelansicht eine kleine Vorschau statt eines Symbols zeigen.",
1692 ),
1693 ("thumbnails_label", "Vorschaubilder zeigen"),
1694 ("type", "Typ"),
1695 ("unlock", "Freigabe öffnen"),
1696 ("unsaved_changes", "Ungespeicherte Änderungen"),
1697 ("until", "Bis"),
1698 ("upload_abort", "Abbrechen"),
1699 ("upload_aborted", "Abgebrochen"),
1700 ("upload_active_n", "{} aktiv"),
1701 (
1702 "upload_apply_all",
1703 "Auch auf Dateien anwenden, die während des Uploads entstehen",
1704 ),
1705 (
1706 "upload_check_failed",
1707 "Prüfung auf vorhandene Dateien fehlgeschlagen: {}",
1708 ),
1709 ("upload_clear", "Aus der Liste entfernen"),
1710 ("upload_clear_finished", "Abgeschlossene entfernen"),
1711 ("upload_collapse", "Einklappen"),
1712 ("upload_complete", "Hochladen abgeschlossen"),
1713 (
1714 "upload_conflict_question",
1715 "Die folgenden Dateien existieren bereits. Überschreiben oder überspringen?",
1716 ),
1717 ("upload_drop_hint", "Zum Hochladen hier ablegen"),
1718 ("upload_errors_n", "{} fehlgeschlagen"),
1719 (
1720 "upload_exists_ask",
1721 "„{}“ ist während des Uploads auf dem Server entstanden.",
1722 ),
1723 ("upload_expand", "Ausklappen"),
1724 ("upload_failed", "Fehlgeschlagen"),
1725 ("upload_files", "Dateien hochladen"),
1726 ("upload_folder", "Ordner hochladen"),
1727 ("upload_n_files", "{} Dateien"),
1728 ("upload_pause", "Pausieren"),
1729 ("upload_paused", "Pausiert"),
1730 ("upload_preparing", "Wird vorbereitet…"),
1731 ("upload_resume", "Fortsetzen"),
1732 ("upload_show_graph", "Details und Geschwindigkeitsverlauf"),
1733 ("upload_skip", "Überspringen"),
1734 ("upload_skipped_n", "{} übersprungen"),
1735 ("upload_speed", "{}/s"),
1736 ("upload_waiting", "Wartet auf Ihre Antwort"),
1737 ("uploads", "Uploads"),
1738 ("uploads_empty", "Noch keine Uploads"),
1739 ("use_passkey", "Passkey verwenden"),
1740 (
1741 "use_passkey_hint",
1742 "Lassen Sie den Namen leer, außer Ihr Passkey braucht ihn.",
1743 ),
1744 ("user_created", "Benutzer erstellt"),
1745 ("user_delete_err", "Benutzer konnte nicht gelöscht werden"),
1746 ("user_disabled", "deaktiviert"),
1747 ("user_name_example", "z. B. alice"),
1748 (
1749 "user_save_err",
1750 "Benutzer konnte nicht gespeichert werden: {}",
1751 ),
1752 ("user_updated", "Benutzer aktualisiert"),
1753 ("user_you", "(Sie)"),
1754 ("users", "Benutzer"),
1755 ("week_monday", "Montag"),
1756 ("week_saturday", "Samstag"),
1757 ("week_start", "Woche beginnt am"),
1758 ("week_start_desc", "Der erste Wochentag im Kalender."),
1759 ("week_sunday", "Sonntag"),
1760 ("your_shares", "Ihre Freigaben"),
1761];
1762
1763/// French translations.
1764const FR: &[(&str, &str)] = &[
1765 ("active_can_signin", "Actif (peut se connecter)"),
1766 ("add_app_password", "Créer un mot de passe d'application"),
1767 ("add_folder", "Ajouter un dossier…"),
1768 ("add_here", "Ajouter ce dossier"),
1769 ("add_passkey", "Ajouter une clé d'accès"),
1770 ("administrator", "Administrateur"),
1771 ("all_shares", "Tous les partages"),
1772 (
1773 "all_shares_hint",
1774 "Tous les liens de ce serveur, groupés par le compte qui les a créés.",
1775 ),
1776 (
1777 "allow_editing",
1778 "Autoriser la modification (lecture-écriture)",
1779 ),
1780 ("allow_rw_shares", "Autoriser les partages modifiables"),
1781 (
1782 "allow_rw_shares_desc",
1783 "Autoriser les utilisateurs à créer des liens de partage en lecture-écriture. Désactivé par défaut.",
1784 ),
1785 ("and_more", "…et {} autres"),
1786 ("app_password_label", "Nom de ce mot de passe d'application"),
1787 ("app_password_removed", "Mot de passe d'application révoqué"),
1788 (
1789 "app_password_secret_once",
1790 "Copiez-le maintenant. Il ne sera plus jamais affiché.",
1791 ),
1792 ("app_passwords", "Mots de passe d'application"),
1793 (
1794 "app_passwords_hint",
1795 "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.",
1796 ),
1797 ("cancel", "Annuler"),
1798 (
1799 "cant_delete_self",
1800 "Vous ne pouvez pas supprimer votre propre compte",
1801 ),
1802 ("close", "Fermer"),
1803 ("close_esc", "Fermer (Échap)"),
1804 ("copied", "Copié"),
1805 ("copy", "Copier"),
1806 ("copy_dav_link", "Copier le lien WebDAV"),
1807 ("copy_here", "Copier ici"),
1808 ("copy_link", "Copier le lien"),
1809 ("copy_manual", "Copiez le lien manuellement"),
1810 ("copy_n_to", "Copier {} éléments vers…"),
1811 ("copy_to", "Copier « {} » vers…"),
1812 ("create", "Créer"),
1813 ("create_admin", "Créer le compte administrateur"),
1814 ("create_link", "Créer le lien"),
1815 ("create_user", "Créer l'utilisateur"),
1816 ("creating", "Création…"),
1817 ("ct_type_cell", "portable"),
1818 ("ct_type_fax", "fax"),
1819 ("ct_type_home", "domicile"),
1820 ("ct_type_other", "autre"),
1821 ("ct_type_work", "travail"),
1822 ("custom", "Personnalisé…"),
1823 (
1824 "default_root_desc",
1825 "Ouvrir ce dossier au chargement de la page et via le lien d'accueil.",
1826 ),
1827 ("default_root_label", "Dossier par défaut"),
1828 ("default_root_none", "Aperçu des dossiers"),
1829 ("delete", "Supprimer"),
1830 ("delete_all", "Tout supprimer"),
1831 (
1832 "delete_all_msg",
1833 "Supprimer les {} liens de partage ? Toute personne les possédant perdra l'accès. Cette action est irréversible.",
1834 ),
1835 ("delete_all_title", "Supprimer tous les partages ?"),
1836 (
1837 "delete_all_user_msg",
1838 "Supprimer tous les liens de partage de « {} » ? Toute personne les possédant perdra l'accès. Cette action est irréversible.",
1839 ),
1840 (
1841 "delete_folder_msg",
1842 "Supprimer le dossier « {} » et tout son contenu ?\nCette action est irréversible.",
1843 ),
1844 (
1845 "delete_msg",
1846 "Supprimer « {} » ?\nCette action est irréversible.",
1847 ),
1848 (
1849 "delete_n_msg",
1850 "Supprimer {} éléments ?\nCette action est irréversible.",
1851 ),
1852 (
1853 "delete_partial",
1854 "{} des {} liens n'ont pas pu être supprimés",
1855 ),
1856 ("delete_share", "Supprimer le partage"),
1857 ("delete_user", "Supprimer l'utilisateur"),
1858 (
1859 "delete_user_confirm",
1860 "Supprimer l'utilisateur « {} » ? Cette action est irréversible.",
1861 ),
1862 ("deleted", "Supprimé"),
1863 ("deleted_n_shares", "{} partage(s) supprimé(s)"),
1864 ("discard", "Abandonner"),
1865 (
1866 "discard_question",
1867 "Abandonner vos modifications et fermer l'éditeur ?",
1868 ),
1869 ("dismiss", "Ignorer"),
1870 ("dismiss_error", "Ignorer l'erreur"),
1871 ("done", "Terminé"),
1872 ("download", "Télécharger"),
1873 (
1874 "download_formats_msg",
1875 "Choisissez un format d'archivage pour le dossier.",
1876 ),
1877 ("download_started", "Téléchargement démarré"),
1878 ("download_title", "Télécharger « {} »"),
1879 ("edit", "Modifier"),
1880 ("edit_user_title", "Modifier « {} »"),
1881 ("empty_folder", "Ce dossier est vide."),
1882 (k::ERR_ADMIN_ONLY, "réservé aux administrateurs"),
1883 (k::ERR_ALREADY_SET_UP, "le serveur est déjà configuré"),
1884 (
1885 k::ERR_APP_PASSWORD_LIMIT,
1886 "Ce compte possède déjà le nombre maximal de mots de passe d'application.",
1887 ),
1888 (
1889 k::ERR_APP_PASSWORD_NOT_FOUND,
1890 "Aucun mot de passe d'application correspondant.",
1891 ),
1892 (k::ERR_BAD_ACTION, "action=content attendu"),
1893 (k::ERR_BAD_BODY, "corps de requête invalide"),
1894 (k::ERR_BAD_EXPIRES_AT, "la date d'expiration est invalide"),
1895 (
1896 k::ERR_BAD_FORMAT,
1897 "le format doit être zip, tar, tar.gz ou tar.zst",
1898 ),
1899 (
1900 k::ERR_BAD_MULTIPART,
1901 "multipart/form-data avec boundary attendu",
1902 ),
1903 (k::ERR_BAD_PART_NAME, "nom de partie invalide"),
1904 (
1905 k::ERR_BAD_POST,
1906 "POST attend un téléversement multipart, une mutation JSON ou ?action=mkdir/create-file",
1907 ),
1908 (k::ERR_BAD_UPLOAD, "données de téléversement invalides"),
1909 (
1910 k::ERR_BAD_UPLOAD_PATH,
1911 "chemin de fichier invalide dans le téléversement",
1912 ),
1913 (
1914 k::ERR_CHALLENGE_EXPIRED,
1915 "Cela a pris trop de temps. Veuillez réessayer.",
1916 ),
1917 (
1918 k::ERR_DEFAULT_CALENDAR,
1919 "Le calendrier qui reçoit les invitations ne peut pas être supprimé.",
1920 ),
1921 (k::ERR_DST_REQUIRED, "dst_root_id est requis"),
1922 (k::ERR_FILE_NAME_REQUIRED, "un nom de fichier est requis"),
1923 (k::ERR_FILES_EXIST, "certains fichiers existent déjà"),
1924 (k::ERR_FOLDER_EXISTS, "un dossier avec ce nom existe déjà"),
1925 (k::ERR_FOLDER_NAME_REQUIRED, "un nom de dossier est requis"),
1926 (k::ERR_FS_CONFLICT, "existe déjà"),
1927 (k::ERR_FS_FORBIDDEN, "accès refusé"),
1928 (k::ERR_FS_NOT_A_DIR, "ce n'est pas un dossier"),
1929 (k::ERR_FS_NOT_FOUND, "dossier introuvable"),
1930 (k::ERR_FS_ROOT_MISSING, "le dossier configuré n'existe plus"),
1931 (k::ERR_INTERNAL, "erreur interne"),
1932 (k::ERR_INVALID_CREDENTIALS, "nom ou mot de passe incorrect"),
1933 (
1934 k::ERR_INVALID_DEFAULT_ROOT,
1935 "le dossier par défaut ne fait pas partie de vos dossiers",
1936 ),
1937 (k::ERR_INVALID_LANGUAGE, "balise de langue invalide"),
1938 (k::ERR_INVALID_WEEK_START, "début de semaine invalide"),
1939 (
1940 k::ERR_LAST_ADMIN,
1941 "impossible de supprimer le dernier administrateur actif",
1942 ),
1943 (
1944 k::ERR_LAST_ADMIN_DELETE,
1945 "impossible de supprimer le dernier administrateur actif",
1946 ),
1947 (
1948 k::ERR_LOCKED_OUT,
1949 "Le compte n'aurait alors plus aucun moyen de connexion.",
1950 ),
1951 (
1952 k::ERR_MODE_NEEDS_PASSKEY,
1953 "Ajoutez une clé d'accès avant d'exiger les deux.",
1954 ),
1955 (
1956 k::ERR_MODE_NEEDS_PASSWORD,
1957 "Définissez un mot de passe avant d'exiger les deux.",
1958 ),
1959 (k::ERR_NAME_LENGTH, "le nom doit contenir 1 à 64 caractères"),
1960 (k::ERR_NEW_NAME_REQUIRED, "new_name est requis"),
1961 (k::ERR_NO_FILES_UPLOADED, "aucun fichier n'a été téléversé"),
1962 (k::ERR_NO_SUCH_FOLDER, "ce dossier n'existe pas"),
1963 (k::ERR_NOT_A_FILE, "ce n'est pas un fichier"),
1964 (k::ERR_NOT_SIGNED_IN, "non connecté"),
1965 (
1966 k::ERR_OWN_ACCOUNT,
1967 "vous ne pouvez pas désactiver votre propre compte",
1968 ),
1969 (
1970 k::ERR_OWN_ADMIN,
1971 "vous ne pouvez pas retirer vos propres droits d'administrateur",
1972 ),
1973 (
1974 k::ERR_OWN_DELETE,
1975 "vous ne pouvez pas supprimer votre propre compte",
1976 ),
1977 (k::ERR_PART_NO_NAME, "partie sans nom"),
1978 (
1979 k::ERR_PASSKEY_DUPLICATE,
1980 "Cette clé d'accès est déjà enregistrée.",
1981 ),
1982 (
1983 k::ERR_PASSKEY_FAILED,
1984 "Cette clé d'accès n'a pas pu être utilisée.",
1985 ),
1986 (
1987 k::ERR_PASSKEY_LAST_CREDENTIAL,
1988 "Définissez un mot de passe avant de retirer votre dernière clé d'accès.",
1989 ),
1990 (
1991 k::ERR_PASSKEY_LIMIT,
1992 "Ce compte a déjà autant de clés d'accès que permis.",
1993 ),
1994 (
1995 k::ERR_PASSKEY_MALFORMED,
1996 "Le navigateur a envoyé des données illisibles.",
1997 ),
1998 (k::ERR_PASSKEY_NOT_FOUND, "Clé d'accès introuvable."),
1999 (
2000 k::ERR_PASSKEY_ORIGIN,
2001 "Les clés d'accès sont configurées pour une autre adresse.",
2002 ),
2003 (
2004 k::ERR_PASSKEY_UNAVAILABLE,
2005 "Les clés d'accès ne sont pas disponibles ici.",
2006 ),
2007 (
2008 k::ERR_PASSWORD_LAST_CREDENTIAL,
2009 "Ajoutez une clé d'accès avant de retirer votre mot de passe.",
2010 ),
2011 (
2012 k::ERR_PASSWORD_SHORT,
2013 "le mot de passe doit contenir au moins 8 caractères",
2014 ),
2015 (k::ERR_PATH_REQUIRED, "un chemin dans le dossier est requis"),
2016 (k::ERR_READ_ONLY_FOLDER, "dossier en lecture seule"),
2017 (
2018 k::ERR_REQUIRED_BY_MODE,
2019 "Ce compte exige un mot de passe et une clé d'accès.",
2020 ),
2021 (k::ERR_ROOT_FORBIDDEN, "dossier inaccessible"),
2022 (
2023 k::ERR_RW_RO_FOLDER,
2024 "ce dossier est en lecture seule pour vous, il ne peut donc pas être partagé en écriture",
2025 ),
2026 (
2027 k::ERR_RW_SHARES_DISABLED,
2028 "les partages modifiables sont désactivés",
2029 ),
2030 (k::ERR_SAVE_FAILED, "impossible d'enregistrer le fichier"),
2031 (
2032 k::ERR_SEARCH_BAD_SCOPE,
2033 "la portée doit être name, content ou both",
2034 ),
2035 (
2036 k::ERR_SEARCH_FORBIDDEN,
2037 "la recherche nécessite une session connectée",
2038 ),
2039 (
2040 k::ERR_SESSION_EXPIRED,
2041 "session expirée, veuillez vous connecter à nouveau",
2042 ),
2043 (k::ERR_SHARE_EXPIRED, "ce partage a expiré"),
2044 (
2045 k::ERR_SHARE_LOCKED,
2046 "Ce partage est protégé par un mot de passe.",
2047 ),
2048 (
2049 k::ERR_SHARE_NO_PASSWORD,
2050 "Ce partage n'a pas de mot de passe.",
2051 ),
2052 (k::ERR_SHARE_NOT_FOUND, "partage introuvable"),
2053 (
2054 k::ERR_SHARE_TOKEN_FORBIDDEN,
2055 "un jeton de partage ne peut pas être utilisé ici ; connectez-vous à la place",
2056 ),
2057 (k::ERR_SHARE_WRONG_PASSWORD, "Mot de passe incorrect."),
2058 (
2059 k::ERR_TOO_LARGE_PREVIEW,
2060 "fichier trop volumineux pour l'aperçu",
2061 ),
2062 (
2063 k::ERR_TOO_LARGE_SAVE,
2064 "fichier trop volumineux pour être enregistré",
2065 ),
2066 (k::ERR_USER_EXISTS, "un utilisateur avec ce nom existe déjà"),
2067 (k::ERR_USER_NOT_FOUND, "utilisateur introuvable"),
2068 ("exclude_dup_err", "Ce dossier est déjà exclu."),
2069 ("exclude_folder", "Exclure un dossier…"),
2070 ("exclude_here", "Exclure ce dossier"),
2071 (
2072 "exclude_root_err",
2073 "La racine entière ne peut pas être exclue ; cela désactiverait la recherche.",
2074 ),
2075 ("expires", "Expire"),
2076 ("expires_at", "Expire le {}"),
2077 ("expiry_1d", "1 jour"),
2078 ("expiry_1h", "1 heure"),
2079 ("expiry_1mo", "1 mois"),
2080 ("expiry_1w", "1 semaine"),
2081 ("file", "Fichier"),
2082 ("file_changed", "Fichier modifié sur disque"),
2083 ("file_created", "Fichier créé"),
2084 ("file_info", "Informations"),
2085 ("file_name", "Nom du fichier"),
2086 ("file_not_found", "Fichier introuvable"),
2087 ("files", "Fichiers"),
2088 ("fmt_tar", "Tar"),
2089 ("fmt_targz", "Tar + gzip"),
2090 ("fmt_tarzst", "Tar + zstd"),
2091 ("fmt_zip", "Zip"),
2092 ("folder", "Dossier"),
2093 ("folder_created", "Dossier créé"),
2094 (
2095 "folder_gone_msg",
2096 "Ce dossier n'est plus accessible. Choisissez-en un autre dans le panneau latéral.",
2097 ),
2098 ("folder_gone_title", "Dossier indisponible"),
2099 ("folder_name", "Nom du dossier"),
2100 ("folders", "Dossiers"),
2101 (
2102 "folders_paths_hint",
2103 "Les chemins sont relatifs à la racine du serveur. « . » désigne toute la racine.",
2104 ),
2105 ("grid_view", "Vue en grille"),
2106 ("info", "Infos"),
2107 ("keep_editing", "Continuer à modifier"),
2108 ("lang_auto", "Automatique"),
2109 ("lang_de", "Allemand"),
2110 ("lang_en", "Anglais"),
2111 ("lang_fr", "Français"),
2112 ("language", "Langue"),
2113 (
2114 "language_desc",
2115 "La langue de l'interface. « Automatique » utilise la langue de votre navigateur.",
2116 ),
2117 ("link_copied", "Lien copié dans le presse-papiers"),
2118 ("list_view", "Vue en liste"),
2119 ("load_latest", "Charger la version la plus récente"),
2120 ("loading", "Chargement…"),
2121 ("loading_share", "Chargement du partage…"),
2122 ("location", "Emplacement"),
2123 ("log_out", "Se déconnecter"),
2124 ("login_subtitle", "Connectez-vous pour continuer."),
2125 ("manage", "Gérer"),
2126 ("menu", "Menu"),
2127 ("meta_created", "créé le {}"),
2128 ("meta_expires", "expire le {}"),
2129 ("mode_ro", "lecture seule"),
2130 ("mode_rw", "lecture-écriture"),
2131 ("modified", "Modifié"),
2132 (
2133 "modified_after",
2134 "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.",
2135 ),
2136 ("more_actions", "Plus d'actions"),
2137 ("move", "Déplacer"),
2138 ("move_here", "Déplacer ici"),
2139 ("move_n_to", "Déplacer {} éléments vers…"),
2140 ("move_to", "Déplacer « {} » vers…"),
2141 ("moved", "Déplacé"),
2142 ("name", "Nom"),
2143 ("name_taken", "Ce nom est déjà utilisé"),
2144 ("need_folder", "Donnez au moins un dossier à l'utilisateur."),
2145 ("never", "Jamais"),
2146 ("never_expires", "N'expire jamais"),
2147 ("new_file", "Nouveau fichier"),
2148 ("new_folder", "Nouveau dossier"),
2149 ("new_name", "Nouveau nom"),
2150 ("new_password", "Nouveau mot de passe"),
2151 (
2152 "new_password_hint",
2153 "Laissez vide pour conserver votre mot de passe actuel.",
2154 ),
2155 (
2156 "new_password_keep",
2157 "Nouveau mot de passe (laisser vide pour conserver)",
2158 ),
2159 ("new_user", "Nouvel utilisateur"),
2160 ("no_app_passwords", "Aucun mot de passe d'application."),
2161 (
2162 "no_folders_msg",
2163 "Aucun administrateur ne vous a encore attribué de dossier.",
2164 ),
2165 ("no_folders_title", "Aucun dossier disponible"),
2166 ("no_passkeys", "Aucune clé d'accès pour l'instant."),
2167 (
2168 "no_password_set",
2169 "Ce compte se connecte uniquement avec des clés d'accès.",
2170 ),
2171 ("no_preview", "Aperçu non disponible"),
2172 (
2173 "no_preview_msg",
2174 "L'application ne peut pas afficher « {} » ici.",
2175 ),
2176 ("no_shares", "Aucun partage pour l'instant"),
2177 ("no_subfolders", "Aucun sous-dossier"),
2178 ("no_users", "Aucun utilisateur."),
2179 ("open", "Ouvrir"),
2180 ("open_in_new_tab", "Ouvrir dans un nouvel onglet"),
2181 ("open_menu", "Ouvrir le menu"),
2182 ("or_label", "ou"),
2183 ("overwrite", "Écraser"),
2184 (
2185 "overwrite_question",
2186 "Les fichiers suivants existent déjà. Les écraser ?",
2187 ),
2188 ("page_first", "Première page"),
2189 ("page_goto", "Page"),
2190 ("page_last", "Dernière page"),
2191 ("page_next", "Page suivante"),
2192 ("page_prev", "Page précédente"),
2193 ("page_size", "Entrées par page"),
2194 ("page_size_n", "{} par page"),
2195 ("passkey_added", "Clé d'accès ajoutée"),
2196 ("passkey_added_on", "Ajoutée {}"),
2197 ("passkey_label", "Nom de cette clé d'accès"),
2198 ("passkey_last_used", "Dernière utilisation {}"),
2199 ("passkey_needs_name", "Exige votre nom d'utilisateur"),
2200 (
2201 "passkey_needs_name_hint",
2202 "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.",
2203 ),
2204 ("passkey_never_used", "Jamais utilisée"),
2205 ("passkey_not_used", "Aucune clé d'accès n'a été utilisée."),
2206 ("passkey_removed", "Clé d'accès retirée"),
2207 (
2208 "passkey_unsupported",
2209 "Ce navigateur ne peut pas utiliser de clés d'accès.",
2210 ),
2211 ("passkeys", "Clés d'accès"),
2212 (
2213 "passkeys_hint",
2214 "Une clé d'accès vous connecte avec votre empreinte, votre visage ou une clé de sécurité.",
2215 ),
2216 ("password", "Mot de passe"),
2217 ("password_min_hint", "au moins 8 caractères"),
2218 ("password_removed", "Mot de passe retiré"),
2219 (
2220 "password_resets_signin",
2221 "Définir un mot de passe supprime aussi les clés d'accès de ce compte et lève toute exigence à deux facteurs.",
2222 ),
2223 ("pim_accept", "Accepter"),
2224 ("pim_access", "Accès"),
2225 ("pim_add", "Ajouter"),
2226 ("pim_address", "Adresse pour les applications"),
2227 ("pim_address_book", "Carnet d'adresses"),
2228 ("pim_address_books", "Carnets d'adresses"),
2229 ("pim_agenda", "Agenda"),
2230 ("pim_all_day", "Toute la journée"),
2231 ("pim_all_events", "Tous les événements de la série"),
2232 ("pim_anniversary", "Anniversaire de mariage"),
2233 ("pim_app_passwords", "Créer un mot de passe d'application"),
2234 ("pim_attendees", "Participants"),
2235 ("pim_auto", "automatique"),
2236 ("pim_back", "Retour"),
2237 ("pim_birthday", "Anniversaire"),
2238 ("pim_birthdays", "Anniversaires"),
2239 ("pim_calendar", "Calendrier"),
2240 ("pim_calendars", "Calendriers"),
2241 ("pim_cancelled", "Annulé"),
2242 ("pim_categories", "Catégories"),
2243 ("pim_clients", "Applications"),
2244 (
2245 "pim_collection_urls",
2246 "Adresses des calendriers et carnets d'adresses",
2247 ),
2248 ("pim_color", "Couleur"),
2249 ("pim_connect", "Connecter une application"),
2250 (
2251 "pim_connect_title",
2252 "Connecter une application de calendrier ou de contacts",
2253 ),
2254 ("pim_contacts", "Contacts"),
2255 ("pim_created", "Créé"),
2256 ("pim_custom_color", "Couleur personnalisée"),
2257 ("pim_decline", "Refuser"),
2258 (
2259 "pim_default_hint",
2260 "Ce calendrier reçoit les invitations. Il ne peut pas être supprimé.",
2261 ),
2262 (
2263 "pim_delete_msg",
2264 "Tout son contenu est supprimé. Les participants à vos réunions reçoivent une annulation.",
2265 ),
2266 ("pim_delete_title", "Supprimer « {} » ?"),
2267 ("pim_description", "Description"),
2268 ("pim_detail", "Détails"),
2269 ("pim_detail_busy", "Heures occupées seulement"),
2270 ("pim_detail_full", "Tous les détails"),
2271 ("pim_directory", "Annuaire"),
2272 ("pim_email", "E-mail"),
2273 ("pim_events_n", "{} événements"),
2274 ("pim_events_one", "1 événement"),
2275 ("pim_export", "Exporter"),
2276 ("pim_feeds_of", "Flux de {}"),
2277 ("pim_file", "Fichier"),
2278 ("pim_from_organizer", "De {}"),
2279 ("pim_from_time", "à partir de {}"),
2280 ("pim_general", "Général"),
2281 (
2282 "pim_generated_hint",
2283 "Le serveur le remplit. Il est en lecture seule.",
2284 ),
2285 ("pim_group", "Groupe"),
2286 ("pim_hide", "Masquer"),
2287 (
2288 "pim_hint_apple",
2289 "Apple : ajoutez un compte CalDAV et un compte CardDAV avec l'adresse du serveur. Apple exige HTTPS.",
2290 ),
2291 (
2292 "pim_hint_davx5",
2293 "Android : dans DAVx⁵, connectez-vous avec URL et nom d'utilisateur, et utilisez l'adresse du serveur.",
2294 ),
2295 (
2296 "pim_hint_gnome",
2297 "GNOME et Evolution : ajoutez un compte CalDAV ou WebDAV avec l'adresse du serveur.",
2298 ),
2299 (
2300 "pim_hint_thunderbird",
2301 "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.",
2302 ),
2303 ("pim_import", "Importer"),
2304 ("pim_import_done", "{} nouveaux, {} mis à jour."),
2305 ("pim_import_file", "Importer un fichier…"),
2306 (
2307 "pim_import_hint_cal",
2308 "Ajoute les événements d'un fichier .ics à ce calendrier. Un événement déjà présent est mis à jour.",
2309 ),
2310 (
2311 "pim_import_hint_cards",
2312 "Ajoute les contacts d'un fichier .vcf à ce carnet d'adresses. Un contact déjà présent est mis à jour.",
2313 ),
2314 (
2315 "pim_import_new_hint_cal",
2316 "Crée un agenda avec les événements d'un fichier .ics.",
2317 ),
2318 (
2319 "pim_import_new_hint_cards",
2320 "Crée un carnet d'adresses avec les contacts d'un fichier .vcf.",
2321 ),
2322 (
2323 "pim_import_nothing",
2324 "Rien n'a pu être importé, donc rien n'a été créé.",
2325 ),
2326 ("pim_import_skipped", "{} ignorés :"),
2327 ("pim_imported_as", "Importé sous « {} »."),
2328 ("pim_importing", "Importation…"),
2329 (
2330 "pim_inv_series_hint",
2331 "Votre réponse vaut pour toute la série.",
2332 ),
2333 ("pim_invitations", "Invitations"),
2334 ("pim_kind_resource", "Ressource"),
2335 ("pim_kind_room", "Salle"),
2336 ("pim_link", "Lien"),
2337 ("pim_link_busy", "heures occupées seulement"),
2338 ("pim_link_full", "tous les détails"),
2339 ("pim_link_revoked", "Lien révoqué"),
2340 ("pim_links", "Liens publics"),
2341 (
2342 "pim_links_hint",
2343 "Toute personne ayant le lien peut s'abonner. Certains agendas, comme Google Agenda et Outlook.com, exigent un lien sans mot de passe.",
2344 ),
2345 (
2346 "pim_links_hint_cards",
2347 "Toute personne ayant le lien peut télécharger les contacts une fois. Les applications ne suivent pas les modifications.",
2348 ),
2349 ("pim_location", "Lieu"),
2350 ("pim_manage", "Paramètres"),
2351 ("pim_manage_of", "Paramètres de {}"),
2352 ("pim_members", "Membres"),
2353 ("pim_mode_ro", "Lecture seule"),
2354 ("pim_mode_rw", "Lecture et écriture"),
2355 (
2356 "pim_mode_schedule",
2357 "Lecture, écriture et envoi d'invitations",
2358 ),
2359 ("pim_month", "Mois"),
2360 ("pim_more_n", "+{} autres"),
2361 ("pim_name_from_file", "Tiré du fichier si vide"),
2362 ("pim_nav", "Calendrier et contacts"),
2363 ("pim_new_address_book", "Nouveau carnet d'adresses"),
2364 (
2365 "pim_new_book_from_file",
2366 "Nouveau carnet d'adresses depuis un fichier",
2367 ),
2368 ("pim_new_calendar", "Nouveau calendrier"),
2369 (
2370 "pim_new_calendar_from_file",
2371 "Nouvel agenda depuis un fichier",
2372 ),
2373 ("pim_new_from_file", "Nouveau depuis un fichier…"),
2374 ("pim_new_room", "Nouvelle salle"),
2375 ("pim_next_month", "Mois suivant"),
2376 (
2377 "pim_no_contacts",
2378 "Pas encore de contacts. Ajoutez-en avec une application de contacts ou une importation.",
2379 ),
2380 (
2381 "pim_no_events_agenda",
2382 "Aucun événement dans les 7 prochains jours.",
2383 ),
2384 ("pim_no_events_day", "Aucun événement ce jour-là."),
2385 ("pim_no_invitations", "Aucune invitation en attente."),
2386 ("pim_no_links", "Aucun lien public."),
2387 ("pim_no_match", "Aucun contact ne correspond."),
2388 ("pim_no_rooms", "Aucune salle ni ressource."),
2389 ("pim_no_shares", "Partagé avec personne."),
2390 ("pim_no_title", "(sans titre)"),
2391 ("pim_not_contact", "Cette entrée n'est pas un contact."),
2392 ("pim_not_event", "Cette entrée n'est pas un événement."),
2393 ("pim_note", "Note"),
2394 ("pim_optional", "facultatif"),
2395 ("pim_organizer", "Organisateur"),
2396 (
2397 "pim_own_empty",
2398 "Aucun lien public, et rien de partagé avec d'autres utilisateurs.",
2399 ),
2400 (
2401 "pim_own_hint",
2402 "Liens publics vers vos calendriers et carnets d'adresses, et ce que vous partagez avec d'autres utilisateurs. Les réglages de chaque collection les gèrent aussi.",
2403 ),
2404 ("pim_own_lends", "Partagé avec d'autres utilisateurs"),
2405 ("pim_own_links", "Vos liens publics"),
2406 (
2407 "pim_password_hint",
2408 "Utilisez un mot de passe d'application plutôt que celui de votre compte.",
2409 ),
2410 ("pim_phone", "Téléphone"),
2411 (
2412 "pim_pick_contact",
2413 "Choisissez un contact pour voir les détails.",
2414 ),
2415 ("pim_postal", "Adresse"),
2416 ("pim_prev_month", "Mois précédent"),
2417 ("pim_ps_accepted", "Accepté"),
2418 ("pim_ps_declined", "Refusé"),
2419 ("pim_ps_delegated", "Délégué"),
2420 ("pim_ps_needs_action", "Pas encore de réponse"),
2421 ("pim_ps_tentative", "Peut-être"),
2422 ("pim_receives_invitations", "Reçoit les invitations"),
2423 ("pim_remove_from_list", "Retirer de ma liste"),
2424 (
2425 "pim_remove_msg",
2426 "Vous ne le voyez plus. Le propriétaire peut le partager à nouveau.",
2427 ),
2428 ("pim_removed", "Retiré de votre liste"),
2429 ("pim_repeats", "Répétition"),
2430 ("pim_replied", "Réponse envoyée"),
2431 (
2432 "pim_room_delete_confirm",
2433 "Supprimer « {} » ? Ses réservations sont perdues.",
2434 ),
2435 ("pim_room_display", "Nom affiché"),
2436 (
2437 "pim_room_name",
2438 "Nom (fait partie de l'adresse, non modifiable)",
2439 ),
2440 ("pim_rooms", "Salles et ressources"),
2441 (
2442 "pim_rooms_hint",
2443 "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.",
2444 ),
2445 ("pim_rrule_count", "{} fois"),
2446 ("pim_rrule_daily", "Tous les jours"),
2447 ("pim_rrule_daily_n", "Tous les {} jours"),
2448 ("pim_rrule_last_day", "dernier jour"),
2449 ("pim_rrule_month_day", "le {}"),
2450 ("pim_rrule_monthly", "Tous les mois"),
2451 ("pim_rrule_monthly_n", "Tous les {} mois"),
2452 ("pim_rrule_nth", "{} {}"),
2453 ("pim_rrule_ord_1", "1er"),
2454 ("pim_rrule_ord_2", "2e"),
2455 ("pim_rrule_ord_3", "3e"),
2456 ("pim_rrule_ord_4", "4e"),
2457 ("pim_rrule_ord_5", "5e"),
2458 ("pim_rrule_ord_last", "dernier"),
2459 ("pim_rrule_until", "jusqu'au {}"),
2460 ("pim_rrule_weekly", "Toutes les semaines"),
2461 ("pim_rrule_weekly_n", "Toutes les {} semaines"),
2462 ("pim_rrule_yearly", "Tous les ans"),
2463 ("pim_rrule_yearly_n", "Tous les {} ans"),
2464 ("pim_save_err", "Impossible d'enregistrer : {}"),
2465 ("pim_search_contacts", "Rechercher des contacts"),
2466 ("pim_server_address", "Adresse du serveur"),
2467 (
2468 "pim_server_address_hint",
2469 "Si une application ne trouve pas le serveur, utilisez cette adresse :",
2470 ),
2471 ("pim_shared_by", "Partagé par {}"),
2472 ("pim_shared_ok", "Partagé avec {}"),
2473 ("pim_shared_with_me", "Partagés avec moi"),
2474 ("pim_sharing", "Partage"),
2475 (
2476 "pim_sharing_hint",
2477 "Partager avec un autre compte de ce serveur.",
2478 ),
2479 ("pim_show", "Afficher"),
2480 ("pim_show_all", "Tout afficher"),
2481 ("pim_show_only", "Afficher seulement celui-ci"),
2482 ("pim_skip_component", "ce type n'est pas accepté ici"),
2483 ("pim_skip_invalid", "données invalides ou incomplètes"),
2484 ("pim_skip_size", "trop volumineux"),
2485 (
2486 "pim_skip_uid",
2487 "le même UID existe déjà dans un autre calendrier",
2488 ),
2489 ("pim_subscribe", "S'abonner"),
2490 ("pim_tentative", "Peut-être"),
2491 ("pim_this_event", "Seulement cet événement"),
2492 ("pim_today", "Aujourd'hui"),
2493 (
2494 "pim_transparent",
2495 "Afficher comme libre : les événements ne bloquent pas de créneaux dans les invitations",
2496 ),
2497 (
2498 "pim_truncated",
2499 "Tous les événements ne tiennent pas dans cette vue. Masquez des calendriers pour voir le reste.",
2500 ),
2501 ("pim_unshare", "Ne plus partager"),
2502 ("pim_unshared", "N'est plus partagé"),
2503 ("pim_until_time", "jusqu'à {}"),
2504 ("pim_upcoming", "7 prochains jours"),
2505 ("pim_user", "Nom d'utilisateur"),
2506 ("pim_user_name", "Nom d'utilisateur"),
2507 ("pim_website", "Site web"),
2508 ("pim_when", "Quand"),
2509 ("pim_your_answer", "Votre réponse"),
2510 ("profile", "Profil"),
2511 (
2512 "profile_save_err",
2513 "Impossible d'enregistrer le profil : {}",
2514 ),
2515 ("profile_saved", "Profil enregistré"),
2516 (
2517 "pw_short",
2518 "Le mot de passe doit contenir au moins 8 caractères.",
2519 ),
2520 ("read_only_badge", "Lecture seule"),
2521 ("read_only_hint", "Dossier en lecture seule"),
2522 ("refresh", "Actualiser"),
2523 ("refresh_folders", "Actualiser vos dossiers"),
2524 ("remove_folder", "Retirer le dossier"),
2525 ("remove_password", "Retirer le mot de passe"),
2526 (
2527 "remove_password_desc",
2528 "Se connecter uniquement avec des clés d'accès. Exige au moins une clé d'accès.",
2529 ),
2530 ("rename", "Renommer"),
2531 ("rename_title", "Renommer « {} »"),
2532 ("renamed", "Renommé"),
2533 ("repeat_password", "Répéter le mot de passe"),
2534 ("retry", "Réessayer"),
2535 ("root_dup_err", "Ce dossier est déjà dans la liste."),
2536 (
2537 "rw_disabled",
2538 "Les partages modifiables sont désactivés par le serveur.",
2539 ),
2540 (
2541 "rw_ro_folder",
2542 "Ce dossier est en lecture seule, le partage l'est donc aussi.",
2543 ),
2544 ("save", "Enregistrer"),
2545 ("save_profile", "Enregistrer le profil"),
2546 ("save_settings", "Enregistrer les paramètres"),
2547 ("saved", "Enregistré"),
2548 ("saving", "Enregistrement…"),
2549 ("search", "Rechercher"),
2550 ("search_both", "Les deux"),
2551 ("search_collapse_all", "Tout replier"),
2552 ("search_content", "Contenu"),
2553 ("search_excludes", "Exclu de la recherche"),
2554 ("search_excludes_empty", "Aucun dossier exclu."),
2555 ("search_expand_all", "Tout déplier"),
2556 ("search_failed", "La recherche a échoué."),
2557 ("search_goto", "Afficher dans le dossier"),
2558 ("search_here", "Rechercher ici"),
2559 ("search_in", "Rechercher dans…"),
2560 ("search_in_folder", "Rechercher dans ce dossier"),
2561 ("search_in_n_files", "dans {} fichiers"),
2562 ("search_n_matches", "{} correspondances"),
2563 ("search_n_results", "{} résultats"),
2564 ("search_name", "Nom"),
2565 ("search_no_results", "aucun résultat"),
2566 (
2567 "search_placeholder",
2568 "Rechercher dans les fichiers et leur contenu",
2569 ),
2570 ("search_run", "Rechercher"),
2571 ("search_scanned", "{} fichiers parcourus"),
2572 ("search_show_more", "Afficher {} de plus"),
2573 ("search_shown_of", "{} sur {} affichés"),
2574 ("search_skipped", "{} ignorés (plus de 10 Mio)"),
2575 ("search_stop", "Arrêter"),
2576 ("search_stopped", "arrêté · {} résultats"),
2577 ("search_took", "{} ms"),
2578 ("searching", "recherche…"),
2579 (
2580 "second_factor_passkey",
2581 "Confirmez maintenant avec votre clé d'accès.",
2582 ),
2583 ("second_factor_password", "Saisissez le mot de passe de {}."),
2584 ("security", "Sécurité"),
2585 (
2586 "select_folder_msg",
2587 "Choisissez un dossier dans le panneau latéral pour commencer à naviguer.",
2588 ),
2589 ("select_folder_title", "Choisir un dossier"),
2590 ("server", "Serveur"),
2591 ("server_root", "Racine du serveur"),
2592 ("server_unreachable", "Le serveur est injoignable."),
2593 ("settings", "Paramètres"),
2594 (
2595 "settings_save_err",
2596 "Impossible d'enregistrer les paramètres : {}",
2597 ),
2598 ("settings_saved", "Paramètres enregistrés"),
2599 (
2600 "setup_intro",
2601 "Premier démarrage : créez le compte administrateur. Cet utilisateur peut gérer les autres utilisateurs et les paramètres du serveur.",
2602 ),
2603 (
2604 "setup_pw_mismatch",
2605 "Les mots de passe ne correspondent pas.",
2606 ),
2607 ("share", "Partager"),
2608 ("share_create_err", "Impossible de créer le partage : {}"),
2609 ("share_delete_err", "Impossible de supprimer le partage"),
2610 ("share_deleted", "Partage supprimé"),
2611 (
2612 "share_dialog_hint",
2613 "Crée un lien pour cet élément. Les liens modifiables permettent aux destinataires de téléverser et de modifier.",
2614 ),
2615 ("share_expired", "Partage expiré"),
2616 ("share_expired_msg", "Ce lien de partage n'est plus actif."),
2617 ("share_link", "Lien de partage"),
2618 ("share_locked_title", "Mot de passe requis"),
2619 ("share_not_found", "Partage introuvable"),
2620 (
2621 "share_not_found_msg",
2622 "Ce lien est invalide ou le partage a été supprimé.",
2623 ),
2624 ("share_owner_disabled", "compte désactivé"),
2625 (
2626 "share_password_hint",
2627 "Facultatif. Les visiteurs doivent le saisir avant d'ouvrir le partage, au moins 8 caractères.",
2628 ),
2629 (
2630 "share_perm_ro",
2631 "Toute personne possédant ce lien peut lire « {} ».",
2632 ),
2633 (
2634 "share_perm_rw",
2635 "Toute personne possédant ce lien peut lire et modifier « {} ».",
2636 ),
2637 ("share_protected", "Protégé par mot de passe"),
2638 ("share_title", "Partager {}"),
2639 ("shares", "Partages"),
2640 ("shares_delete_err", "Impossible de supprimer les partages"),
2641 (
2642 "shares_empty_hint",
2643 "Faites un clic droit sur un fichier ou un dossier, puis choisissez « Partager » pour créer un lien.",
2644 ),
2645 (
2646 "shares_view_hint",
2647 "Liens que vous avez créés. Faites un clic droit sur un fichier ou un dossier, puis choisissez « Partager » pour en ajouter un.",
2648 ),
2649 ("sign_in", "Se connecter"),
2650 ("signin_both", "Mot de passe et clé d'accès"),
2651 (
2652 "signin_both_desc",
2653 "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.",
2654 ),
2655 ("signin_either", "Mot de passe ou clé d'accès"),
2656 (
2657 "signin_either_desc",
2658 "L'un ou l'autre suffit pour se connecter.",
2659 ),
2660 ("signin_requirement", "Exigence de connexion"),
2661 (
2662 "single_click_desc",
2663 "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.",
2664 ),
2665 ("single_click_label", "Ouvrir au clic simple"),
2666 ("size", "Taille"),
2667 ("some_files_exist", "Certains fichiers existent déjà"),
2668 ("sort_asc", "Croissant"),
2669 ("sort_by", "Trier par"),
2670 ("sort_desc", "Décroissant"),
2671 ("theme_auto", "Auto"),
2672 ("theme_dark", "Sombre"),
2673 ("theme_light", "Clair"),
2674 ("theme_title", "Thème : {} (cliquer pour changer)"),
2675 (
2676 "thumbnails_desc",
2677 "Afficher un aperçu à la place d'une icône pour les images et les vidéos en vue grille.",
2678 ),
2679 ("thumbnails_label", "Afficher les miniatures"),
2680 ("type", "Type"),
2681 ("unlock", "Ouvrir le partage"),
2682 ("unsaved_changes", "Modifications non enregistrées"),
2683 ("until", "Jusqu'au"),
2684 ("upload_abort", "Interrompre"),
2685 ("upload_aborted", "Interrompu"),
2686 ("upload_active_n", "{} en cours"),
2687 (
2688 "upload_apply_all",
2689 "Appliquer aussi aux fichiers qui apparaissent pendant le téléversement",
2690 ),
2691 (
2692 "upload_check_failed",
2693 "Impossible de vérifier les fichiers existants : {}",
2694 ),
2695 ("upload_clear", "Retirer de la liste"),
2696 ("upload_clear_finished", "Effacer les terminés"),
2697 ("upload_collapse", "Réduire"),
2698 ("upload_complete", "Téléversement terminé"),
2699 (
2700 "upload_conflict_question",
2701 "Les fichiers suivants existent déjà. Les remplacer ou les ignorer ?",
2702 ),
2703 ("upload_drop_hint", "Déposer ici pour téléverser"),
2704 ("upload_errors_n", "{} en échec"),
2705 (
2706 "upload_exists_ask",
2707 "« {} » est apparu sur le serveur pendant le téléversement.",
2708 ),
2709 ("upload_expand", "Développer"),
2710 ("upload_failed", "Échec"),
2711 ("upload_files", "Téléverser des fichiers"),
2712 ("upload_folder", "Téléverser un dossier"),
2713 ("upload_n_files", "{} fichiers"),
2714 ("upload_pause", "Mettre en pause"),
2715 ("upload_paused", "En pause"),
2716 ("upload_preparing", "Préparation…"),
2717 ("upload_resume", "Reprendre"),
2718 ("upload_show_graph", "Détails et graphique de vitesse"),
2719 ("upload_skip", "Ignorer"),
2720 ("upload_skipped_n", "{} ignorés"),
2721 ("upload_speed", "{}/s"),
2722 ("upload_waiting", "En attente de votre réponse"),
2723 ("uploads", "Téléversements"),
2724 ("uploads_empty", "Aucun téléversement pour l'instant"),
2725 ("use_passkey", "Utiliser une clé d'accès"),
2726 (
2727 "use_passkey_hint",
2728 "Laissez le nom vide, sauf si votre clé d'accès en a besoin.",
2729 ),
2730 ("user_created", "Utilisateur créé"),
2731 ("user_delete_err", "Impossible de supprimer l'utilisateur"),
2732 ("user_disabled", "désactivé"),
2733 ("user_name_example", "p. ex. alice"),
2734 (
2735 "user_save_err",
2736 "Impossible d'enregistrer l'utilisateur : {}",
2737 ),
2738 ("user_updated", "Utilisateur mis à jour"),
2739 ("user_you", "(vous)"),
2740 ("users", "Utilisateurs"),
2741 ("week_monday", "Lundi"),
2742 ("week_saturday", "Samedi"),
2743 ("week_start", "La semaine commence le"),
2744 (
2745 "week_start_desc",
2746 "Le premier jour de la semaine dans le calendrier.",
2747 ),
2748 ("week_sunday", "Dimanche"),
2749 ("your_shares", "Vos partages"),
2750];
2751
2752#[cfg(test)]
2753mod tests {
2754 use super::*;
2755
2756 fn keys<'a>(table: &'a [(&'a str, &'a str)]) -> Vec<&'a str> {
2757 table.iter().map(|(k, _)| *k).collect()
2758 }
2759
2760 #[test]
2761 fn tables_are_sorted() {
2762 // `find` binary-searches, so an out-of-order entry is unreachable.
2763 for (name, table) in [("EN", EN), ("DE", DE), ("FR", FR)] {
2764 let ks = keys(table);
2765 let mut sorted = ks.clone();
2766 sorted.sort_unstable();
2767 assert_eq!(ks, sorted, "{name} table is not sorted by key");
2768 }
2769 }
2770
2771 #[test]
2772 fn no_duplicate_keys() {
2773 for (name, table) in [("EN", EN), ("DE", DE), ("FR", FR)] {
2774 let mut ks = keys(table);
2775 ks.sort_unstable();
2776 let dups = ks
2777 .windows(2)
2778 .filter(|w| w[0] == w[1])
2779 .map(|w| w[0])
2780 .collect::<Vec<_>>();
2781 assert!(dups.is_empty(), "{name} duplicates: {dups:?}");
2782 }
2783 }
2784
2785 #[test]
2786 fn translations_cover_all_keys() {
2787 // Full parity: DE and FR must translate every EN key (both
2788 // directions), so no string can silently fall back to English.
2789 let en = keys(EN);
2790 for (name, table) in [("DE", DE), ("FR", FR)] {
2791 let other = keys(table);
2792 assert_eq!(
2793 en.len(),
2794 other.len(),
2795 "{name} has {} keys, EN has {}",
2796 other.len(),
2797 en.len()
2798 );
2799 for k in &other {
2800 assert!(en.contains(k), "{name} key not in EN: {k}");
2801 }
2802 }
2803 }
2804}
2805