1use alloc::boxed::Box;
46use alloc::collections::BTreeMap;
47use alloc::string::String;
48use alloc::vec::Vec;
49use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
50
51use crate::{Command, Mi};
52
53#[path = "i18n_locale.rs"]
54mod regional;
55pub use regional::*;
56#[path = "i18n_msg.rs"]
57mod message;
58pub use message::{Arg, msg};
59#[path = "i18n_collate.rs"]
60mod collation;
61pub use collation::*;
62
63pub const LANG_DE: u32 = 0;
64pub const LANG_EN: u32 = 1;
65
66static LANG: AtomicU32 = AtomicU32::new(LANG_DE);
67static LIB: AtomicU32 = AtomicU32::new(0);
69static LIB_RTL: AtomicBool = AtomicBool::new(false);
71const RTL_LANGS: [&str; 10] = ["ar", "he", "iw", "fa", "ur", "ps", "sd", "ug", "yi", "dv"];
72static EXPLICIT: AtomicBool = AtomicBool::new(false);
74static EXPLICIT_CODE: rt::sync::SpinLock<Option<String>> = rt::sync::SpinLock::new(None);
75static USER: rt::sync::SpinLock<Vec<String>> = rt::sync::SpinLock::new(Vec::new());
77
78pub fn set_language(lang: u32) {
80 EXPLICIT.store(true, Ordering::Relaxed);
81 *EXPLICIT_CODE.lock() = None;
82 select(lang);
83}
84
85fn select(lang: u32) {
86 LANG.store(lang, Ordering::Relaxed);
87 let code = language_code();
88 let lib = if code == "iw" { "he" } else { code.as_str() };
89 LIB.store(LIB_LANGS.iter().position(|l| *l == lib).unwrap_or(1) as u32, Ordering::Relaxed);
90 LIB_RTL.store(RTL_LANGS.contains(&code.as_str()), Ordering::Relaxed);
91}
92
93fn columns() -> Vec<String> {
95 match *APP.lock() {
96 Some(c) if !c.langs.is_empty() => c.langs.clone(),
97 _ => alloc::vec![String::from("de"), String::from("en")],
98 }
99}
100
101#[cfg(jfgui_dev)]
104pub(crate) fn language_codes() -> Vec<String> {
105 columns()
106}
107
108pub fn language_code() -> String {
110 let cols = columns();
111 let code = cols.get(language() as usize).map_or("en", |c| c.as_str());
112 String::from(code.split(['-', '_']).next().unwrap_or(code)).to_ascii_lowercase()
113}
114
115pub fn set_language_code(code: &str) -> u32 {
118 EXPLICIT.store(true, Ordering::Relaxed);
119 *EXPLICIT_CODE.lock() = Some(String::from(code));
120 let k = pick(&[code]);
121 select(k);
122 k
123}
124
125fn pick<W: AsRef<str>>(wanted: &[W]) -> u32 {
127 let cols = columns();
128 let k = negotiate(&cols, wanted).or_else(|| negotiate(&cols, &["en"])).unwrap_or(0);
129 k as u32
130}
131
132pub fn negotiate<A: AsRef<str>, W: AsRef<str>>(available: &[A], wanted: &[W]) -> Option<usize> {
135 fn primary(t: &str) -> &str {
136 t.split(['-', '_']).next().unwrap_or(t)
137 }
138 for w in wanted {
139 let w = w.as_ref();
140 if let Some(k) = available.iter().position(|a| a.as_ref().replace('_', "-").eq_ignore_ascii_case(&w.replace('_', "-"))) {
141 return Some(k);
142 }
143 if let Some(k) = available.iter().position(|a| primary(a.as_ref()).eq_ignore_ascii_case(primary(w))) {
144 return Some(k);
145 }
146 }
147 None
148}
149
150pub fn user_languages() -> Vec<String> {
152 let u = USER.lock().clone();
153 if u.is_empty() { alloc::vec![String::from("de-DE")] } else { u }
154}
155
156pub fn set_user_languages<W: AsRef<str>>(list: &[W]) {
158 *USER.lock() = list.iter().filter_map(|w| plat::locale_tag(w.as_ref())).collect();
159 if APP.lock().is_some() && !EXPLICIT.load(Ordering::Relaxed) {
160 select(pick(&user_languages()));
161 }
162}
163
164pub fn use_system() {
166 if !use_env() {
167 set_user_languages(&plat::system_languages());
168 if let Some(t) = plat::system_locale() {
169 set_locale(&t);
170 }
171 }
172}
173
174fn use_env() -> bool {
177 let Some(v) = plat::arg_value("--lang").or_else(|| plat::env("jfgui_LANG")).filter(|v| !v.trim().is_empty()) else { return false };
178 let list: Vec<&str> = v.split([':', ',']).map(str::trim).filter(|t| !t.is_empty()).collect();
179 set_user_languages(&list);
180 if let Some(first) = list.first() {
181 set_locale(first);
182 }
183 true
184}
185
186pub(crate) fn boot(headless: bool) {
189 if headless {
190 use_env();
191 } else {
192 use_system();
193 }
194}
195
196pub fn rtl_language() -> bool {
199 LIB_RTL.load(Ordering::Relaxed)
200}
201
202pub fn language() -> u32 {
204 LANG.load(Ordering::Relaxed)
205}
206
207const LIB_LANGS: [&str; 9] = ["de", "en", "fr", "es", "it", "nl", "pl", "ar", "he"];
209
210static LIB_TEXTS: &[[&str; 9]] = &[
213 ["Öffnen", "Open", "Ouvrir", "Abrir", "Apri", "Openen", "Otwórz", "فتح", "פתיחה"],
214 ["Speichern", "Save", "Enregistrer", "Guardar", "Salva", "Opslaan", "Zapisz", "حفظ", "שמירה"],
215 ["Speichern unter", "Save as", "Enregistrer sous", "Guardar como", "Salva con nome", "Opslaan als", "Zapisz jako", "حفظ باسم", "שמירה בשם"],
216 ["Abbrechen", "Cancel", "Annuler", "Cancelar", "Annulla", "Annuleren", "Anuluj", "إلغاء", "ביטול"],
217 ["Schließen", "Close", "Fermer", "Cerrar", "Chiudi", "Sluiten", "Zamknij", "إغلاق", "סגירה"],
218 ["Zurücksetzen", "Reset", "Réinitialiser", "Restablecer", "Reimposta", "Opnieuw instellen", "Resetuj", "إعادة تعيين", "איפוס"],
219 ["Dateiname:", "File name:", "Nom du fichier\u{A0}:", "Nombre de archivo:", "Nome file:", "Bestandsnaam:", "Nazwa pliku:", "اسم الملف:", "שם קובץ:"],
220 ["Ordner auswählen", "Select folder", "Sélectionner un dossier", "Seleccionar carpeta", "Seleziona cartella", "Map selecteren", "Wybierz folder", "تحديد مجلد", "בחירת תיקייה"],
221 ["Neuer Ordner", "New folder", "Nouveau dossier", "Nueva carpeta", "Nuova cartella", "Nieuwe map", "Nowy folder", "مجلد جديد", "תיקייה חדשה"],
222 ["Übergeordneter Ordner", "Parent folder", "Dossier parent", "Carpeta superior", "Cartella superiore", "Bovenliggende map", "Folder nadrzędny", "المجلد الأصل", "תיקיית אב"],
223 ["Startordner", "Home folder", "Dossier personnel", "Carpeta personal", "Cartella personale", "Persoonlijke map", "Folder domowy", "المجلد الرئيسي", "תיקיית הבית"],
224 [
225 "Der Pfad ist zu lang.",
226 "The path is too long.",
227 "Le chemin d’accès est trop long.",
228 "La ruta es demasiado larga.",
229 "Il percorso è troppo lungo.",
230 "Het pad is te lang.",
231 "Ścieżka jest za długa.",
232 "المسار طويل جدًا.",
233 "הנתיב ארוך מדי.",
234 ],
235 [
236 "Die Datei wurde nicht gefunden.",
237 "The file was not found.",
238 "Le fichier est introuvable.",
239 "No se encontró el archivo.",
240 "Impossibile trovare il file.",
241 "Het bestand is niet gevonden.",
242 "Nie znaleziono pliku.",
243 "تعذر العثور على الملف.",
244 "הקובץ לא נמצא.",
245 ],
246 ["Aufwärts", "Up", "Monter", "Subir", "Su", "Omhoog", "W górę", "لأعلى", "למעלה"],
247 ["Zurück", "Back", "Précédent", "Atrás", "Indietro", "Vorige", "Wstecz", "السابق", "הקודם"],
248 ["Weiter", "Next", "Suivant", "Siguiente", "Avanti", "Volgende", "Dalej", "التالي", "הבא"],
249 ["Fertigstellen", "Finish", "Terminer", "Finalizar", "Fine", "Voltooien", "Zakończ", "إنهاء", "סיום"],
250 ["Weitere Befehle", "More commands", "Plus de commandes", "Más comandos", "Altri comandi", "Meer opdrachten", "Więcej poleceń", "مزيد من الأوامر", "פקודות נוספות"],
251 [
252 "Vorherige Register",
253 "Previous tabs",
254 "Onglets précédents",
255 "Pestañas anteriores",
256 "Schede precedenti",
257 "Vorige tabbladen",
258 "Poprzednie karty",
259 "علامات التبويب السابقة",
260 "כרטיסיות קודמות",
261 ],
262 ["Weitere Register", "More tabs", "Plus d’onglets", "Más pestañas", "Altre schede", "Meer tabbladen", "Więcej kart", "مزيد من علامات التبويب", "כרטיסיות נוספות"],
263 ["Aufklappen", "Expand", "Développer", "Expandir", "Espandi", "Uitvouwen", "Rozwiń", "توسيع", "הרחבה"],
264 ["Zuklappen", "Collapse", "Réduire", "Contraer", "Comprimi", "Samenvouwen", "Zwiń", "طي", "כיווץ"],
265 [
266 "Navigation umschalten",
267 "Toggle navigation",
268 "Afficher/masquer la navigation",
269 "Mostrar u ocultar navegación",
270 "Mostra/nascondi navigazione",
271 "Navigatie weergeven/verbergen",
272 "Pokaż/ukryj nawigację",
273 "إظهار التنقل أو إخفاؤه",
274 "הצגה/הסתרה של הניווט",
275 ],
276 ["Heute", "Today", "Aujourd’hui", "Hoy", "Oggi", "Vandaag", "Dzisiaj", "اليوم", "היום"],
277 ["Vorheriger Monat", "Previous month", "Mois précédent", "Mes anterior", "Mese precedente", "Vorige maand", "Poprzedni miesiąc", "الشهر السابق", "החודש הקודם"],
278 ["Nächster Monat", "Next month", "Mois suivant", "Mes siguiente", "Mese successivo", "Volgende maand", "Następny miesiąc", "الشهر التالي", "החודש הבא"],
279 ["Strg", "Ctrl", "Ctrl", "Ctrl", "Ctrl", "Ctrl", "Ctrl", "Ctrl", "Ctrl"],
281 ["Umschalt", "Shift", "Maj", "Mayús", "Maiusc", "Shift", "Shift", "Shift", "Shift"],
282 ["Alt", "Alt", "Alt", "Alt", "Alt", "Alt", "Alt", "Alt", "Alt"],
283 ["Entf", "Del", "Suppr", "Supr", "Canc", "Del", "Del", "Del", "Del"],
284 ["Einfg", "Ins", "Inser", "Insert", "Ins", "Ins", "Ins", "Ins", "Ins"],
285 ["Pos1", "Home", "Origine", "Inicio", "Home", "Home", "Home", "Home", "Home"],
286 ["Ende", "End", "Fin", "Fin", "Fine", "End", "End", "End", "End"],
287 ["Bild auf", "PgUp", "Pg préc", "Re Pág", "PgSu", "PgUp", "PgUp", "PgUp", "PgUp"],
288 ["Bild ab", "PgDn", "Pg suiv", "Av Pág", "PgGiù", "PgDn", "PgDn", "PgDn", "PgDn"],
289 ["Leertaste", "Space", "Espace", "Espacio", "Spazio", "Spatie", "Spacja", "Space", "Space"],
290 ["Eingabe", "Enter", "Entrée", "Entrar", "Invio", "Enter", "Enter", "Enter", "Enter"],
291 ["Rücktaste", "Backspace", "Retour arrière", "Retroceso", "Backspace", "Backspace", "Backspace", "Backspace", "Backspace"],
292 ["Esc", "Esc", "Échap", "Esc", "Esc", "Esc", "Esc", "Esc", "Esc"],
293 ["Nach-links", "Left", "Gauche", "Izquierda", "Sinistra", "Links", "W lewo", "Left", "Left"],
294 ["Nach-rechts", "Right", "Droite", "Derecha", "Destra", "Rechts", "W prawo", "Right", "Right"],
295 ["Nach-oben", "Up", "Haut", "Arriba", "Su", "Omhoog", "W górę", "Up", "Up"],
296 ["Nach-unten", "Down", "Bas", "Abajo", "Giù", "Omlaag", "W dół", "Down", "Down"],
297 ["Allgemein", "General", "Général", "General", "Generale", "Algemeen", "Ogólne", "عام", "כללי"],
299 [
300 "Wird nach einem Neustart wirksam.",
301 "Takes effect after a restart.",
302 "Prend effet après un redémarrage.",
303 "Surte efecto después de reiniciar.",
304 "Ha effetto dopo il riavvio.",
305 "Wordt van kracht na een herstart.",
306 "Zacznie obowiązywać po ponownym uruchomieniu.",
307 "يسري مفعوله بعد إعادة التشغيل.",
308 "ייכנס לתוקף לאחר הפעלה מחדש.",
309 ],
310 ["OK", "OK", "OK", "Aceptar", "OK", "OK", "OK", "موافق", "אישור"],
312 ["Suchen", "Search", "Rechercher", "Buscar", "Cerca", "Zoeken", "Szukaj", "بحث", "חיפוש"],
313 ["Schriftart", "Font", "Police", "Fuente", "Carattere", "Lettertype", "Czcionka", "الخط", "גופן"],
314 [
315 "Schriftschnitt",
316 "Font style",
317 "Style de police",
318 "Estilo de fuente",
319 "Stile carattere",
320 "Tekenstijl",
321 "Styl czcionki",
322 "نمط الخط",
323 "סגנון גופן",
324 ],
325 ["Größe", "Size", "Taille", "Tamaño", "Dimensione", "Grootte", "Rozmiar", "الحجم", "גודל"],
326 ["Vorschau", "Preview", "Aperçu", "Vista previa", "Anteprima", "Voorbeeld", "Podgląd", "معاينة", "תצוגה מקדימה"],
327 ["Achsen", "Axes", "Axes", "Ejes", "Assi", "Assen", "Osie", "المحاور", "צירים"],
328 ["Standard", "Regular", "Normal", "Normal", "Normale", "Normaal", "Normalny", "عادي", "רגיל"],
329 ["Kursiv", "Italic", "Italique", "Cursiva", "Corsivo", "Cursief", "Kursywa", "مائل", "נטוי"],
330 ["Fett", "Bold", "Gras", "Negrita", "Grassetto", "Vet", "Pogrubienie", "غامق", "מודגש"],
331 [
332 "Fett Kursiv",
333 "Bold Italic",
334 "Gras italique",
335 "Negrita cursiva",
336 "Grassetto corsivo",
337 "Vet cursief",
338 "Pogrubiona kursywa",
339 "غامق مائل",
340 "מודגש נטוי",
341 ],
342 [
343 "Keine passende Schrift installiert",
344 "No matching font installed",
345 "Aucune police correspondante installée",
346 "No hay ninguna fuente adecuada instalada",
347 "Nessun carattere adatto installato",
348 "Geen passend lettertype geïnstalleerd",
349 "Brak zainstalowanej pasującej czcionki",
350 "لا يوجد خط مطابق مثبت",
351 "לא מותקן גופן מתאים",
352 ],
353 [
354 "Angezeigt in:",
355 "Shown in:",
356 "Affiché avec\u{A0}:",
357 "Se muestra en:",
358 "Visualizzato in:",
359 "Weergegeven in:",
360 "Wyświetlane czcionką:",
361 "معروض بخط:",
362 "מוצג בגופן:",
363 ],
364 [
366 "Weitere Optionen",
367 "More options",
368 "Plus d’options",
369 "Más opciones",
370 "Altre opzioni",
371 "Meer opties",
372 "Więcej opcji",
373 "مزيد من الخيارات",
374 "אפשרויות נוספות",
375 ],
376 ["Einklappen", "Collapse", "Réduire", "Contraer", "Comprimi", "Samenvouwen", "Zwiń", "طي", "כיווץ"],
377 ["Ausblenden", "Hide", "Masquer", "Ocultar", "Nascondi", "Verbergen", "Ukryj", "إخفاء", "הסתרה"],
378 ["Lösen", "Float", "Détacher", "Desacoplar", "Sgancia", "Losmaken", "Odepnij", "فصل", "ניתוק"],
379 ["Andocken", "Dock", "Ancrer", "Acoplar", "Ancora", "Vastzetten", "Zadokuj", "إرساء", "עגינה"],
380 [
381 "Links andocken",
382 "Dock left",
383 "Ancrer à gauche",
384 "Acoplar a la izquierda",
385 "Ancora a sinistra",
386 "Links vastzetten",
387 "Zadokuj po lewej",
388 "إرساء إلى اليسار",
389 "עגינה לשמאל",
390 ],
391 [
392 "Rechts andocken",
393 "Dock right",
394 "Ancrer à droite",
395 "Acoplar a la derecha",
396 "Ancora a destra",
397 "Rechts vastzetten",
398 "Zadokuj po prawej",
399 "إرساء إلى اليمين",
400 "עגינה לימין",
401 ],
402 [
403 "Unten andocken",
404 "Dock at the bottom",
405 "Ancrer en bas",
406 "Acoplar abajo",
407 "Ancora in basso",
408 "Onderaan vastzetten",
409 "Zadokuj na dole",
410 "إرساء في الأسفل",
411 "עגינה למטה",
412 ],
413 ["Als Register", "As a tab", "Comme onglet", "Como pestaña", "Come scheda", "Als tabblad", "Jako karta", "كعلامة تبويب", "ככרטיסייה"],
414 ["Darüber", "Above", "Au-dessus", "Encima", "Sopra", "Erboven", "Powyżej", "فوق", "מעל"],
415 ["Darunter", "Below", "En dessous", "Debajo", "Sotto", "Eronder", "Poniżej", "تحت", "מתחת"],
416 ["Davor", "Before", "Avant", "Antes", "Prima", "Ervoor", "Przed", "قبل", "לפני"],
417 ["Dahinter", "After", "Après", "Después", "Dopo", "Erna", "Za", "بعد", "אחרי"],
418 ["Keine Vorschläge", "No suggestions", "Aucune suggestion", "No hay sugerencias", "Nessun suggerimento", "Geen suggesties", "Brak sugestii", "لا توجد اقتراحات", "אין הצעות"],
420 [
421 "Vorschläge werden gesucht …",
422 "Looking for suggestions…",
423 "Recherche de suggestions…",
424 "Buscando sugerencias…",
425 "Ricerca dei suggerimenti…",
426 "Suggesties zoeken…",
427 "Wyszukiwanie sugestii…",
428 "جارٍ البحث عن اقتراحات…",
429 "חיפוש הצעות…",
430 ],
431 [
432 "Zum Wörterbuch hinzufügen",
433 "Add to dictionary",
434 "Ajouter au dictionnaire",
435 "Agregar al diccionario",
436 "Aggiungi al dizionario",
437 "Toevoegen aan woordenlijst",
438 "Dodaj do słownika",
439 "إضافة إلى القاموس",
440 "הוספה למילון",
441 ],
442 ["Ignorieren", "Ignore", "Ignorer", "Ignorar", "Ignora", "Negeren", "Ignoruj", "تجاهل", "התעלמות"],
443 ["Zugriff erlauben?", "Allow access?", "Autoriser l’accès\u{A0}?", "¿Permitir el acceso?", "Consentire l’accesso?", "Toegang toestaan?", "Zezwolić na dostęp?", "السماح بالوصول؟", "לאפשר גישה?"],
445 ["Dateien lesen", "Read files", "Lire des fichiers", "Leer archivos", "Leggere file", "Bestanden lezen", "Odczytywać pliki", "قراءة الملفات", "קריאת קבצים"],
446 ["Dateien schreiben", "Write files", "Écrire des fichiers", "Escribir archivos", "Scrivere file", "Bestanden schrijven", "Zapisywać pliki", "كتابة الملفات", "כתיבת קבצים"],
447 ["Ein Programm starten", "Start a program", "Lancer un programme", "Iniciar un programa", "Avviare un programma", "Een programma starten", "Uruchomić program", "تشغيل برنامج", "הפעלת תוכנית"],
448 ["Eine Adresse öffnen", "Open an address", "Ouvrir une adresse", "Abrir una dirección", "Aprire un indirizzo", "Een adres openen", "Otworzyć adres", "فتح عنوان", "פתיחת כתובת"],
449 ["Ein Plugin laden", "Load a plug-in", "Charger un plug-in", "Cargar un complemento", "Caricare un plug-in", "Een plug-in laden", "Wczytać wtyczkę", "تحميل مكوّن إضافي", "טעינת תוסף"],
450 ["Drucken", "Print", "Imprimer", "Imprimir", "Stampare", "Afdrukken", "Drukować", "طباعة", "הדפסה"],
451 [
452 "Gespeicherte Kennwörter verwenden",
453 "Use saved passwords",
454 "Utiliser les mots de passe enregistrés",
455 "Usar contraseñas guardadas",
456 "Usare le password salvate",
457 "Opgeslagen wachtwoorden gebruiken",
458 "Używać zapisanych haseł",
459 "استخدام كلمات المرور المحفوظة",
460 "שימוש בסיסמאות שמורות",
461 ],
462 [
463 "Beim Anmelden starten",
464 "Start at sign-in",
465 "Démarrer à l’ouverture de session",
466 "Iniciar al iniciar sesión",
467 "Avviare all’accesso",
468 "Starten bij aanmelden",
469 "Uruchamiać przy logowaniu",
470 "التشغيل عند تسجيل الدخول",
471 "הפעלה בעת הכניסה",
472 ],
473 ["Klänge abspielen", "Play sounds", "Jouer des sons", "Reproducir sonidos", "Riprodurre suoni", "Geluiden afspelen", "Odtwarzać dźwięki", "تشغيل الأصوات", "השמעת צלילים"],
474 ["Den Standort abfragen", "Get your location", "Connaître votre position", "Consultar su ubicación", "Rilevare la posizione", "Uw locatie opvragen", "Odczytać lokalizację", "معرفة موقعك", "קבלת המיקום שלך"],
475 ["Die Bewegungssensoren lesen", "Read the motion sensors", "Lire les capteurs de mouvement", "Leer los sensores de movimiento", "Leggere i sensori di movimento", "De bewegingssensoren lezen", "Odczytać czujniki ruchu", "قراءة مستشعرات الحركة", "קריאת חיישני התנועה"],
476 [
477 "Eine Netzwerkverbindung aufbauen",
478 "Connect to the network",
479 "Se connecter au réseau",
480 "Conectarse a la red",
481 "Connettersi alla rete",
482 "Verbinding maken met het netwerk",
483 "Łączyć się z siecią",
484 "الاتصال بالشبكة",
485 "התחברות לרשת",
486 ],
487 [
488 "Netzwerkverbindungen annehmen",
489 "Accept network connections",
490 "Accepter des connexions réseau",
491 "Aceptar conexiones de red",
492 "Accettare connessioni di rete",
493 "Netwerkverbindingen accepteren",
494 "Przyjmować połączenia sieciowe",
495 "قبول اتصالات الشبكة",
496 "קבלת חיבורי רשת",
497 ],
498 [
499 "Eine Aktion für den Agenten ausführen",
500 "Run an action for the agent",
501 "Exécuter une action pour l’agent",
502 "Ejecutar una acción para el agente",
503 "Eseguire un’azione per l’agente",
504 "Een actie voor de agent uitvoeren",
505 "Wykonać akcję dla agenta",
506 "تنفيذ إجراء للوكيل",
507 "ביצוע פעולה עבור הסוכן",
508 ],
509 ["Für das Plugin: {}", "For the plug-in: {}", "Pour le plug-in\u{A0}: {}", "Para el complemento: {}", "Per il plug-in: {}", "Voor de plug-in: {}", "Dla wtyczki: {}", "للمكوّن الإضافي: {}", "עבור התוסף: {}"],
510 ["Grund: {}", "Reason: {}", "Motif\u{A0}: {}", "Motivo: {}", "Motivo: {}", "Reden: {}", "Powód: {}", "السبب: {}", "סיבה: {}"],
511 ["Regel: {}", "Rule: {}", "Règle\u{A0}: {}", "Regla: {}", "Regola: {}", "Regel: {}", "Reguła: {}", "القاعدة: {}", "כלל: {}"],
512 ["Einmal erlauben", "Allow once", "Autoriser une fois", "Permitir una vez", "Consenti una volta", "Eenmaal toestaan", "Zezwól raz", "السماح مرة واحدة", "אפשר פעם אחת"],
513 ["Immer erlauben", "Always allow", "Toujours autoriser", "Permitir siempre", "Consenti sempre", "Altijd toestaan", "Zawsze zezwalaj", "السماح دائمًا", "אפשר תמיד"],
514 ["Ablehnen", "Deny", "Refuser", "Denegar", "Nega", "Weigeren", "Odmów", "رفض", "דחה"],
515 ["Nie erlauben", "Never allow", "Ne jamais autoriser", "No permitir nunca", "Non consentire mai", "Nooit toestaan", "Nigdy nie zezwalaj", "عدم السماح أبدًا", "לעולם אל תאפשר"],
516 [
517 "Wird beim nächsten Zugriff gefragt",
518 "Asked on the next access",
519 "Demandé au prochain accès",
520 "Se preguntará en el próximo acceso",
521 "Richiesto al prossimo accesso",
522 "Wordt bij de volgende toegang gevraagd",
523 "Pytanie przy następnym dostępie",
524 "سيُطلب عند الوصول التالي",
525 "תוצג שאלה בגישה הבאה",
526 ],
527 [
528 "Bis zum Programmende erlaubt",
529 "Allowed until the program ends",
530 "Autorisé jusqu’à la fermeture du programme",
531 "Permitido hasta que se cierre el programa",
532 "Consentito fino alla chiusura del programma",
533 "Toegestaan tot het programma sluit",
534 "Dozwolone do zamknięcia programu",
535 "مسموح حتى إغلاق البرنامج",
536 "מותר עד לסגירת התוכנית",
537 ],
538 ["Immer erlaubt", "Always allowed", "Toujours autorisé", "Siempre permitido", "Sempre consentito", "Altijd toegestaan", "Zawsze dozwolone", "مسموح دائمًا", "מותר תמיד"],
539 [
540 "Bis zum Programmende abgelehnt",
541 "Denied until the program ends",
542 "Refusé jusqu’à la fermeture du programme",
543 "Denegado hasta que se cierre el programa",
544 "Negato fino alla chiusura del programma",
545 "Geweigerd tot het programma sluit",
546 "Odmówiono do zamknięcia programu",
547 "مرفوض حتى إغلاق البرنامج",
548 "נדחה עד לסגירת התוכנית",
549 ],
550 ["Nie erlaubt", "Never allowed", "Jamais autorisé", "Nunca permitido", "Mai consentito", "Nooit toegestaan", "Nigdy niedozwolone", "غير مسموح أبدًا", "אסור תמיד"],
551 [
552 "Keine Rückfragen",
553 "No permission questions",
554 "Aucune demande d’autorisation",
555 "No hay solicitudes de permiso",
556 "Nessuna richiesta di autorizzazione",
557 "Geen toestemmingsvragen",
558 "Brak pytań o uprawnienia",
559 "لا توجد طلبات أذونات",
560 "אין בקשות הרשאה",
561 ],
562 ["Alle zurücksetzen", "Reset all", "Tout réinitialiser", "Restablecer todo", "Reimposta tutto", "Alles opnieuw instellen", "Resetuj wszystko", "إعادة تعيين الكل", "איפוס הכול"],
563 ["Sättigung und Helligkeit", "Saturation and brightness", "Saturation et luminosité", "Saturación y brillo", "Saturazione e luminosità", "Verzadiging en helderheid", "Nasycenie i jasność", "التشبع والسطوع", "רוויה ובהירות"],
565 ["Farbton", "Hue", "Teinte", "Matiz", "Tonalità", "Tint", "Odcień", "تدرج اللون", "גוון"],
566 ["Deckkraft", "Opacity", "Opacité", "Opacidad", "Opacità", "Dekking", "Krycie", "العتامة", "אטימות"],
567 ["Farbe vom Bildschirm aufnehmen", "Pick a color from the screen", "Prélever une couleur à l'écran", "Tomar un color de la pantalla", "Preleva un colore dallo schermo", "Kleur van het scherm kiezen", "Pobierz kolor z ekranu", "التقاط لون من الشاشة", "דגימת צבע מהמסך"],
569 ["Teiler", "Splitter", "Séparateur", "Divisor", "Divisore", "Splitser", "Rozdzielacz", "فاصل", "מפריד"],
571 ["Einfügen", "Paste", "Coller", "Pegar", "Incolla", "Plakken", "Wklej", "لصق", "הדבקה"],
573 ["Löschen", "Delete", "Supprimer", "Eliminar", "Elimina", "Verwijderen", "Usuń", "حذف", "מחיקה"],
574 ["Liste", "List", "Liste", "Lista", "Elenco", "Lijst", "Lista", "قائمة", "רשימה"],
575 ["Absatz", "Paragraph", "Paragraphe", "Párrafo", "Paragrafo", "Alinea", "Akapit", "فقرة", "פסקה"],
576 ["Unterstrichen", "Underline", "Souligné", "Subrayado", "Sottolineato", "Onderstrepen", "Podkreślenie", "تسطير", "קו תחתון"],
577 ["Durchgestrichen", "Strikethrough", "Barré", "Tachado", "Barrato", "Doorhalen", "Przekreślenie", "يتوسطه خط", "קו חוצה"],
578 ["Format", "Format", "Format", "Formato", "Formato", "Opmaak", "Formatowanie", "تنسيق", "עיצוב"],
579 ["Textfarbe", "Text color", "Couleur du texte", "Color de texto", "Colore testo", "Tekstkleur", "Kolor tekstu", "لون النص", "צבע טקסט"],
580 ["Hervorhebung", "Highlight", "Surlignage", "Resaltado", "Evidenziazione", "Markering", "Wyróżnienie", "تمييز", "הדגשה"],
581 ["Schriftgröße", "Font size", "Taille de police", "Tamaño de fuente", "Dimensione carattere", "Tekengrootte", "Rozmiar czcionki", "حجم الخط", "גודל גופן"],
582 ["Link", "Link", "Lien", "Enlace", "Collegamento", "Koppeling", "Link", "ارتباط", "קישור"],
583 ["Format löschen", "Clear formatting", "Effacer la mise en forme", "Borrar formato", "Cancella formattazione", "Opmaak wissen", "Wyczyść formatowanie", "مسح التنسيق", "ניקוי עיצוב"],
584 ["Ausrichtung", "Alignment", "Alignement", "Alineación", "Allineamento", "Uitlijning", "Wyrównanie", "محاذاة", "יישור"],
585 ["Einzug", "Indent", "Retrait", "Sangría", "Rientro", "Inspringing", "Wcięcie", "مسافة بادئة", "כניסה"],
586 ["Formatvorlage", "Style", "Style", "Estilo", "Stile", "Stijl", "Styl", "نمط", "סגנון"],
587 ["Ersetzen", "Replace", "Remplacer", "Reemplazar", "Sostituisci", "Vervangen", "Zamień", "استبدال", "החלפה"],
588 ["Link-Adresse", "Link address", "Adresse du lien", "Dirección del enlace", "Indirizzo collegamento", "Koppelingsadres", "Adres linku", "عنوان الارتباط", "כתובת קישור"],
589 ["Link entfernen", "Remove link", "Supprimer le lien", "Quitar enlace", "Rimuovi collegamento", "Koppeling verwijderen", "Usuń link", "إزالة الارتباط", "הסרת קישור"],
590 ["Rückgängig", "Undo", "Annuler", "Deshacer", "Annulla", "Ongedaan maken", "Cofnij", "تراجع", "ביטול פעולה"],
591 ["Wiederholen", "Redo", "Rétablir", "Rehacer", "Ripeti", "Opnieuw", "Ponów", "إعادة", "ביצוע חוזר"],
592 ["Überschrift 1", "Heading 1", "Titre 1", "Título 1", "Titolo 1", "Kop 1", "Nagłówek 1", "عنوان 1", "כותרת 1"],
593 ["Überschrift 2", "Heading 2", "Titre 2", "Título 2", "Titolo 2", "Kop 2", "Nagłówek 2", "عنوان 2", "כותרת 2"],
594 ["Überschrift 3", "Heading 3", "Titre 3", "Título 3", "Titolo 3", "Kop 3", "Nagłówek 3", "عنوان 3", "כותרת 3"],
595 ["Zitat", "Quote", "Citation", "Cita", "Citazione", "Citaat", "Cytat", "اقتباس", "ציטוט"],
596 ["Keine", "None", "Aucune", "Ninguno", "Nessuno", "Geen", "Brak", "بلا", "ללא"],
597 ["Automatisch", "Automatic", "Automatique", "Automático", "Automatico", "Automatisch", "Automatyczny", "تلقائي", "אוטומטי"],
598 ["Linksbündig", "Align left", "Aligner à gauche", "Alinear a la izquierda", "Allinea a sinistra", "Links uitlijnen", "Wyrównaj do lewej", "محاذاة لليسار", "יישור לשמאל"],
599 ["Zentriert", "Center", "Centrer", "Centrar", "Centra", "Centreren", "Wyśrodkuj", "توسيط", "מרכוז"],
600 ["Rechtsbündig", "Align right", "Aligner à droite", "Alinear a la derecha", "Allinea a destra", "Rechts uitlijnen", "Wyrównaj do prawej", "محاذاة لليمين", "יישור לימין"],
601 ["Blocksatz", "Justify", "Justifier", "Justificar", "Giustifica", "Uitvullen", "Wyjustuj", "ضبط", "יישור לשני הצדדים"],
602 ["Aufzählung", "Bullets", "Puces", "Viñetas", "Elenco puntato", "Opsommingstekens", "Punktory", "تعداد نقطي", "תבליטים"],
603 ["Nummerierung", "Numbering", "Numérotation", "Numeración", "Elenco numerato", "Nummering", "Numerowanie", "ترقيم", "מספור"],
604 ["Einzug verkleinern", "Decrease indent", "Diminuer le retrait", "Disminuir sangría", "Riduci rientro", "Inspringing verkleinen", "Zmniejsz wcięcie", "إنقاص المسافة البادئة", "הקטנת כניסה"],
605 ["Einzug vergrößern", "Increase indent", "Augmenter le retrait", "Aumentar sangría", "Aumenta rientro", "Inspringing vergroten", "Zwiększ wcięcie", "زيادة المسافة البادئة", "הגדלת כניסה"],
606 ["Zeilenumbruch", "Line break", "Saut de ligne", "Salto de línea", "Interruzione di riga", "Regeleinde", "Podział wiersza", "فاصل أسطر", "מעבר שורה"],
607 ["Kommentar", "Comment", "Commentaire", "Comentario", "Commento", "Opmerking", "Komentarz", "تعليق", "הערה"],
608 ["Zeilen verschieben", "Move lines", "Déplacer les lignes", "Mover líneas", "Sposta righe", "Regels verplaatsen", "Przenieś wiersze", "نقل الأسطر", "הזזת שורות"],
609 ["Alle ersetzen", "Replace all", "Remplacer tout", "Reemplazar todo", "Sostituisci tutto", "Alles vervangen", "Zamień wszystko", "استبدال الكل", "החלפת הכול"],
610 ["Groß-/Kleinschreibung", "Match case", "Respecter la casse", "Coincidir mayúsculas y minúsculas", "Maiuscole/minuscole", "Hoofdlettergevoelig", "Uwzględnij wielkość liter", "مطابقة حالة الأحرف", "התאמת רישיות"],
611 ["Ganzes Wort", "Whole word", "Mot entier", "Palabra completa", "Parola intera", "Heel woord", "Całe wyrazy", "الكلمة بأكملها", "מילה שלמה"],
612 ["Vorheriger Treffer", "Previous match", "Résultat précédent", "Coincidencia anterior", "Risultato precedente", "Vorige overeenkomst", "Poprzednie wystąpienie", "التطابق السابق", "ההתאמה הקודמת"],
613 ["Nächster Treffer", "Next match", "Résultat suivant", "Coincidencia siguiente", "Risultato successivo", "Volgende overeenkomst", "Następne wystąpienie", "التطابق التالي", "ההתאמה הבאה"],
614 ["Keine Treffer", "No results", "Aucun résultat", "Sin resultados", "Nessun risultato", "Geen resultaten", "Brak wyników", "لا توجد نتائج", "אין תוצאות"],
615 ["Fehler", "Error", "Erreur", "Error", "Errore", "Fout", "Błąd", "خطأ", "שגיאה"],
617 ["Warnung", "Warning", "Avertissement", "Advertencia", "Avviso", "Waarschuwing", "Ostrzeżenie", "تحذير", "אזהרה"],
618 ["Hinweis", "Info", "Info", "Información", "Informazione", "Info", "Informacja", "معلومة", "מידע"],
619 ["Schreiben", "Typing", "Saisie", "Escritura", "Digitazione", "Typen", "Pisanie", "كتابة", "הקלדה"],
620 ["Fließtext", "Normal text", "Texte normal", "Texto normal", "Testo normale", "Normale tekst", "Zwykły tekst", "نص عادي", "טקסט רגיל"],
621 ["Standardschrift", "Default font", "Police par défaut", "Fuente predeterminada", "Carattere predefinito", "Standaardlettertype", "Domyślna czcionka", "الخط الافتراضي", "גופן ברירת מחדל"],
622 ["Dokument", "Document", "Document", "Documento", "Documento", "Document", "Dokument", "مستند", "מסמך"],
624 ["Senden", "Submit", "Envoyer", "Enviar", "Invia", "Verzenden", "Wyślij", "إرسال", "שליחה"],
626 ["Inspektor", "Inspector", "Inspecteur", "Inspector", "Ispettore", "Inspector", "Inspektor", "أداة الفحص", "כלי בדיקה"],
628 ["Auswählen", "Pick", "Choisir", "Elegir", "Scegli", "Kiezen", "Wskaż", "انتقاء", "בחירה"],
629 ["Umrisse", "Outlines", "Contours", "Contornos", "Contorni", "Omtrekken", "Obrysy", "الحدود", "קווי מתאר"],
630 ["Tab-Reihenfolge", "Tab order", "Ordre de tabulation", "Orden de tabulación", "Ordine di tabulazione", "Tabvolgorde", "Kolejność tabulacji", "ترتيب التنقل", "סדר מעבר"],
631 ["Neu gezeichnet", "Repaints", "Zones redessinées", "Zonas repintadas", "Aree ridisegnate", "Hertekend", "Odświeżone obszary", "المناطق المعاد رسمها", "אזורים שצוירו מחדש"],
632 ["Widgets", "Widgets", "Widgets", "Widgets", "Widget", "Widgets", "Widżety", "عناصر الواجهة", "רכיבים"],
633 ["Bildaufbau", "Frame", "Image", "Fotograma", "Fotogramma", "Frame", "Klatka", "الإطار", "פריים"],
634 ["Farben", "Colors", "Couleurs", "Colores", "Colori", "Kleuren", "Kolory", "الألوان", "צבעים"],
635 ["Nichts ausgewählt", "Nothing selected", "Aucune sélection", "Nada seleccionado", "Nessuna selezione", "Niets geselecteerd", "Nic nie zaznaczono", "لم يُحدَّد شيء", "לא נבחר דבר"],
636 [
637 "Klicken Sie auf ein Widget (Esc beendet)",
638 "Click a widget (Esc ends)",
639 "Cliquez sur un widget (Échap pour terminer)",
640 "Haga clic en un widget (Esc para terminar)",
641 "Fai clic su un widget (Esc per terminare)",
642 "Klik op een widget (Esc stopt)",
643 "Kliknij widżet (Esc kończy)",
644 "انقر عنصرًا (Esc للإنهاء)",
645 "לחצו על רכיב (Esc לסיום)",
646 ],
647 ["Kopieren", "Copy", "Copier", "Copiar", "Copia", "Kopiëren", "Kopiuj", "نسخ", "העתקה"],
648 ["Art", "Kind", "Type", "Tipo", "Tipo", "Soort", "Rodzaj", "النوع", "סוג"],
649 ["Kennung", "ID", "Identifiant", "Identificador", "Identificatore", "ID", "Identyfikator", "المعرّف", "מזהה"],
650 ["Beschriftung", "Label", "Libellé", "Etiqueta", "Etichetta", "Label", "Etykieta", "التسمية", "תווית"],
651 ["Rechteck", "Rectangle", "Rectangle", "Rectángulo", "Rettangolo", "Rechthoek", "Prostokąt", "المستطيل", "מלבן"],
652 ["Wert", "Value", "Valeur", "Valor", "Valore", "Waarde", "Wartość", "القيمة", "ערך"],
653 ["Zustand", "State", "État", "Estado", "Stato", "Status", "Stan", "الحالة", "מצב"],
654 ["Ebene", "Layer", "Calque", "Capa", "Livello", "Laag", "Warstwa", "الطبقة", "שכבה"],
655 ["Fenster", "Window", "Fenêtre", "Ventana", "Finestra", "Venster", "Okno", "النافذة", "חלון"],
656 ["Selektor", "Selector", "Sélecteur", "Selector", "Selettore", "Selector", "Selektor", "المحدِّد", "בורר"],
657 ["Durchgänge", "Passes", "Passes", "Pasadas", "Passate", "Passes", "Przebiegi", "التمريرات", "מעברים"],
658 ["Aufbau", "Build", "Construction", "Construcción", "Costruzione", "Opbouw", "Budowanie", "البناء", "בנייה"],
659 ["Zeichnen", "Render", "Rendu", "Renderizado", "Rendering", "Weergave", "Renderowanie", "الرسم", "ציור"],
660 ["Neu gezeichnete Fläche", "Repainted area", "Surface redessinée", "Área repintada", "Area ridisegnata", "Hertekend gebied", "Odświeżony obszar", "المساحة المعاد رسمها", "שטח שצויר מחדש"],
661 ["Zeichenbefehle", "Draw commands", "Commandes de dessin", "Comandos de dibujo", "Comandi di disegno", "Tekenopdrachten", "Polecenia rysowania", "أوامر الرسم", "פקודות ציור"],
662 ["Glyphen-Cache", "Glyph cache", "Cache des glyphes", "Caché de glifos", "Cache dei glifi", "Glyphcache", "Pamięć podręczna glifów", "ذاكرة الحروف المؤقتة", "מטמון גליפים"],
663 ["Hauptfenster", "Main window", "Fenêtre principale", "Ventana principal", "Finestra principale", "Hoofdvenster", "Okno główne", "النافذة الرئيسية", "חלון ראשי"],
664 ["Bau fehlgeschlagen", "Build failed", "Échec de la compilation", "Error de compilación", "Compilazione non riuscita", "Build mislukt", "Kompilacja nie powiodła się", "فشل البناء", "הבנייה נכשלה"],
666 [
667 "Die laufende Fassung bleibt.",
668 "The running version stays.",
669 "La version en cours reste active.",
670 "La versión en ejecución se mantiene.",
671 "La versione in esecuzione resta attiva.",
672 "De draaiende versie blijft actief.",
673 "Działająca wersja pozostaje.",
674 "تبقى النسخة الجارية قيد التشغيل.",
675 "הגרסה הפועלת נשארת.",
676 ],
677 ["Hell", "Light", "Clair", "Claro", "Chiaro", "Licht", "Jasny", "فاتح", "בהיר"],
679 ["Dunkel", "Dark", "Sombre", "Oscuro", "Scuro", "Donker", "Ciemny", "داكن", "כהה"],
680 ["Hoher Kontrast", "High contrast", "Contraste élevé", "Contraste alto", "Contrasto elevato", "Hoog contrast", "Wysoki kontrast", "تباين عالٍ", "ניגודיות גבוהה"],
681 ["Akzent", "Accent", "Accent", "Acento", "Accento", "Accent", "Akcent", "لون التمييز", "צבע הדגשה"],
682 ["Eckenradius", "Corner radius", "Rayon des coins", "Radio de las esquinas", "Raggio degli angoli", "Hoekradius", "Promień narożników", "نصف قطر الزوايا", "רדיוס פינות"],
683 ["Abstände", "Spacing", "Espacement", "Espaciado", "Spaziatura", "Afstand", "Odstępy", "التباعد", "ריווח"],
684 ["Steuerelementhöhe", "Control height", "Hauteur des contrôles", "Altura de los controles", "Altezza dei controlli", "Hoogte van besturingselementen", "Wysokość kontrolek", "ارتفاع عناصر التحكم", "גובה פקדים"],
685 ["Familie", "Family", "Famille", "Familia", "Famiglia", "Familie", "Rodzina", "العائلة", "משפחה"],
686 ["Modus", "Mode", "Mode", "Modo", "Modalità", "Modus", "Tryb", "الوضع", "מצב תצוגה"],
687 ["Stil", "Style", "Style", "Estilo", "Stile", "Stijl", "Styl", "النمط", "סגנון"],
688 ["Sprache", "Language", "Langue", "Idioma", "Lingua", "Taal", "Język", "اللغة", "שפה"],
689 ["Skalierung", "Scale", "Échelle", "Escala", "Scala", "Schaal", "Skala", "التحجيم", "קנה מידה"],
690 ["Textskalierung", "Text scale", "Échelle du texte", "Escala del texto", "Scala del testo", "Tekstschaal", "Skala tekstu", "تحجيم النص", "קנה מידה של טקסט"],
691 ["vom Stil", "from the style", "du style", "del estilo", "dello stile", "van de stijl", "ze stylu", "من النمط", "מהסגנון"],
692 ["Alles zurücksetzen", "Reset all", "Tout réinitialiser", "Restablecer todo", "Reimposta tutto", "Alles opnieuw instellen", "Resetuj wszystko", "إعادة تعيين الكل", "איפוס הכול"],
693 ["Gespeichert: {}", "Saved: {}", "Enregistré\u{A0}: {}", "Guardado: {}", "Salvato: {}", "Opgeslagen: {}", "Zapisano: {}", "تم الحفظ: {}", "נשמר: {}"],
694 ["Nicht gespeichert: {}", "Not saved: {}", "Non enregistré\u{A0}: {}", "No guardado: {}", "Non salvato: {}", "Niet opgeslagen: {}", "Nie zapisano: {}", "لم يُحفظ: {}", "לא נשמר: {}"],
695 ["Das hast du geändert", "What you changed", "Ce que vous avez modifié", "Lo que has cambiado", "Cosa hai modificato", "Wat je hebt gewijzigd", "Co zostało zmienione", "ما غيّرته", "מה ששינית"],
696 ["Theme-Datei", "Theme file", "Fichier de thème", "Archivo de tema", "File del tema", "Themabestand", "Plik motywu", "ملف السمة", "קובץ ערכת נושא"],
697 ["Im Code", "In the code", "Dans le code", "En el código", "Nel codice", "In de code", "W kodzie", "في الشيفرة", "בקוד"],
698 ["Kopiert", "Copied", "Copié", "Copiado", "Copiato", "Gekopieerd", "Skopiowano", "تم النسخ", "הועתק"],
699 ["Änderungen: {}", "Changes: {}", "Modifications\u{A0}: {}", "Cambios: {}", "Modifiche: {}", "Wijzigingen: {}", "Zmiany: {}", "التغييرات: {}", "שינויים: {}"],
700 ["Zurücksetzen: {}", "Reset: {}", "Réinitialiser\u{A0}: {}", "Restablecer: {}", "Reimposta: {}", "Opnieuw instellen: {}", "Resetuj: {}", "إعادة تعيين: {}", "איפוס: {}"],
701 ["Farbwähler", "Color picker", "Sélecteur de couleur", "Selector de color", "Selettore colore", "Kleurkiezer", "Selektor kolorów", "منتقي الألوان", "בורר צבעים"],
702 ["geändert", "changed", "modifié", "cambiado", "modificato", "gewijzigd", "zmieniono", "مُعدَّل", "שונה"],
703 ["Darstellung", "Appearance", "Apparence", "Apariencia", "Aspetto", "Weergave", "Wygląd", "المظهر", "מראה"],
704 ["Maße", "Metrics", "Dimensions", "Medidas", "Misure", "Afmetingen", "Wymiary", "الأبعاد", "מידות"],
705 ["Schrift", "Font", "Police", "Fuente", "Carattere", "Lettertype", "Czcionka", "الخط", "גופן"],
706 ["Änderungen", "Changes", "Modifications", "Cambios", "Modifiche", "Wijzigingen", "Zmiany", "التغييرات", "שינויים"],
707 ["Keine Änderungen", "No changes", "Aucune modification", "Sin cambios", "Nessuna modifica", "Geen wijzigingen", "Brak zmian", "لا توجد تغييرات", "אין שינויים"],
708 ["Pfad der Theme-Datei", "Path of the theme file", "Chemin du fichier de thème", "Ruta del archivo de tema", "Percorso del file del tema", "Pad van het themabestand", "Ścieżka pliku motywu", "مسار ملف السمة", "נתיב קובץ ערכת הנושא"],
709 ["Als Theme speichern", "Save as theme", "Enregistrer comme thème", "Guardar como tema", "Salva come tema", "Opslaan als thema", "Zapisz jako motyw", "حفظ كسمة", "שמירה כערכת נושא"],
710 ["Liste kopieren", "Copy list", "Copier la liste", "Copiar lista", "Copia elenco", "Lijst kopiëren", "Kopiuj listę", "نسخ القائمة", "העתקת הרשימה"],
711 ["Bedienen", "Operate", "Manipuler", "Manejar", "Azionare", "Bedienen", "Obsłuż", "تشغيل", "הפעלה"],
712 ["Skript: {}", "Script: {}", "Script\u{A0}: {}", "Script: {}", "Script: {}", "Script: {}", "Skrypt: {}", "البرنامج النصي: {}", "סקריפט: {}"],
713 ["Klicken", "Click", "Cliquer", "Hacer clic", "Fai clic", "Klikken", "Kliknij", "نقر", "לחיצה"],
714 ["Ziehen", "Drag", "Glisser", "Arrastrar", "Trascina", "Slepen", "Przeciągnij", "سحب", "גרירה"],
715 ["Setzen", "Set", "Définir", "Establecer", "Imposta", "Instellen", "Ustaw", "تعيين", "הגדרה"],
716 ["Text", "Text", "Texte", "Texto", "Testo", "Tekst", "Tekst", "النص", "טקסט"],
717 ["Tippen", "Type", "Saisir", "Escribir", "Digita", "Typen", "Wpisz", "كتابة", "הקלדה"],
718 ["Befehl", "Command", "Commande", "Comando", "Comando", "Opdracht", "Polecenie", "الأمر", "פקודה"],
719 ["Ausführen", "Run", "Exécuter", "Ejecutar", "Esegui", "Uitvoeren", "Uruchom", "تنفيذ", "הרצה"],
720 ["Quelle", "Source", "Source", "Fuente", "Sorgente", "Bron", "Źródło", "المصدر", "מקור"],
722 ["Quelle kopieren", "Copy source", "Copier la source", "Copiar fuente", "Copia sorgente", "Bron kopiëren", "Kopiuj źródło", "نسخ المصدر", "העתקת המקור"],
723 ["Im Editor öffnen", "Open in editor", "Ouvrir dans l'éditeur", "Abrir en el editor", "Apri nell'editor", "Openen in editor", "Otwórz w edytorze", "فتح في المحرر", "פתיחה בעורך"],
724 ["Geöffnet mit {}", "Opened with {}", "Ouvert avec {}", "Abierto con {}", "Aperto con {}", "Geopend met {}", "Otwarto za pomocą {}", "فُتح باستخدام {}", "נפתח באמצעות {}"],
725 [
726 "Kein Editor gefunden: jfgui_EDITOR, VISUAL oder EDITOR setzen",
727 "No editor found: set jfgui_EDITOR, VISUAL or EDITOR",
728 "Aucun éditeur trouvé\u{A0}: définissez jfgui_EDITOR, VISUAL ou EDITOR",
729 "No se encontró ningún editor: defina jfgui_EDITOR, VISUAL o EDITOR",
730 "Nessun editor trovato: impostare jfgui_EDITOR, VISUAL o EDITOR",
731 "Geen editor gevonden: stel jfgui_EDITOR, VISUAL of EDITOR in",
732 "Nie znaleziono edytora: ustaw jfgui_EDITOR, VISUAL lub EDITOR",
733 "لم يُعثر على محرر: اضبط jfgui_EDITOR أو VISUAL أو EDITOR",
734 "לא נמצא עורך: יש להגדיר jfgui_EDITOR, VISUAL או EDITOR",
735 ],
736 [
737 "Die App darf {} nicht starten (PERMISSIONS: process). Quelle kopieren und selbst öffnen.",
738 "The app may not start {} (PERMISSIONS: process). Copy the source and open it yourself.",
739 "L'application ne peut pas lancer {} (PERMISSIONS\u{A0}: process). Copiez la source et ouvrez-la vous-même.",
740 "La aplicación no puede iniciar {} (PERMISSIONS: process). Copie la fuente y ábrala usted mismo.",
741 "L'app non può avviare {} (PERMISSIONS: process). Copia la sorgente e aprila manualmente.",
742 "De app mag {} niet starten (PERMISSIONS: process). Kopieer de bron en open die zelf.",
743 "Aplikacja nie może uruchomić {} (PERMISSIONS: process). Skopiuj źródło i otwórz je samodzielnie.",
744 "لا يُسمح للتطبيق بتشغيل {} (PERMISSIONS: process). انسخ المصدر وافتحه بنفسك.",
745 "לאפליקציה אסור להפעיל את {} (PERMISSIONS: process). יש להעתיק את המקור ולפתוח אותו ידנית.",
746 ],
747 [
748 "Die App fragt, ob sie {} starten darf: nach der Antwort noch einmal öffnen.",
749 "The app asks whether it may start {}: open again after the answer.",
750 "L'application demande si elle peut lancer {}\u{A0}: ouvrez à nouveau après la réponse.",
751 "La aplicación pregunta si puede iniciar {}: vuelva a abrir tras la respuesta.",
752 "L'app chiede se può avviare {}: riaprire dopo la risposta.",
753 "De app vraagt of hij {} mag starten: open opnieuw na het antwoord.",
754 "Aplikacja pyta, czy może uruchomić {}: po odpowiedzi otwórz ponownie.",
755 "يسأل التطبيق عمّا إذا كان يمكنه تشغيل {}: افتح مرة أخرى بعد الإجابة.",
756 "האפליקציה שואלת אם מותר לה להפעיל את {}: יש לפתוח שוב לאחר התשובה.",
757 ],
758 [
759 "Start fehlgeschlagen: {} (Fehler {})",
760 "Could not start {} (error {})",
761 "Impossible de lancer {} (erreur {})",
762 "No se pudo iniciar {} (error {})",
763 "Impossibile avviare {} (errore {})",
764 "Kan {} niet starten (fout {})",
765 "Nie można uruchomić {} (błąd {})",
766 "تعذّر تشغيل {} (الخطأ {})",
767 "לא ניתן להפעיל את {} (שגיאה {})",
768 ],
769 ["Bild", "Image", "Image", "Imagen", "Immagine", "Afbeelding", "Obraz", "صورة", "תמונה"],
771 ["Keine Daten", "No data", "Aucune donnée", "Sin datos", "Nessun dato", "Geen gegevens", "Brak danych", "لا توجد بيانات", "אין נתונים"],
773 ["aktuell", "current", "actuel", "actual", "attuale", "huidig", "bieżąca", "الحالية", "נוכחי"],
774 ["min.", "min", "min", "mín.", "min", "min.", "min.", "الأدنى", "מינימום"],
775 ["max.", "max", "max", "máx.", "max", "max.", "maks.", "الأقصى", "מקסימום"],
776 ["Neue Ausgabe", "New output", "Nouvelle sortie", "Nueva salida", "Nuovo output", "Nieuwe uitvoer", "Nowe dane wyjściowe", "مخرجات جديدة", "פלט חדש"],
778 ["Bereich", "panel", "panneau", "panel", "pannello", "paneel", "panel", "لوحة", "חלונית"],
781 ["Bezeichnung", "label", "étiquette", "etiqueta", "etichetta", "label", "etykieta", "تسمية", "תווית"],
782 ["Schaltfläche", "push button", "bouton", "botón", "pulsante", "knop", "przycisk", "زر", "לחצן"],
783 ["Kontrollkästchen", "check box", "case à cocher", "casilla", "casella di controllo", "selectievakje", "pole wyboru", "خانة اختيار", "תיבת סימון"],
784 ["Optionsfeld", "radio button", "bouton radio", "botón de opción", "pulsante di opzione", "keuzerondje", "przycisk opcji", "زر اختيار", "לחצן אפשרות"],
785 ["Umschalter", "toggle switch", "interrupteur", "interruptor", "interruttore", "schakelaar", "przełącznik", "مفتاح تبديل", "מתג"],
786 ["Schieberegler", "slider", "curseur", "control deslizante", "dispositivo di scorrimento", "schuifregelaar", "suwak", "شريط تمرير", "מחוון"],
787 ["Fortschrittsanzeige", "progress bar", "barre de progression", "barra de progreso", "barra di avanzamento", "voortgangsbalk", "pasek postępu", "شريط التقدم", "סרגל התקדמות"],
788 ["Eingabefeld", "entry", "zone de saisie", "campo de texto", "campo di testo", "invoerveld", "pole tekstowe", "حقل إدخال", "שדה קלט"],
789 ["Verweis", "link", "lien", "enlace", "collegamento", "koppeling", "łącze", "ارتباط", "קישור"],
790 ["Listenfeld", "list box", "zone de liste", "cuadro de lista", "casella di riepilogo", "keuzelijst", "pole listy", "مربع قائمة", "תיבת רשימה"],
791 ["Listeneintrag", "list item", "élément de liste", "elemento de lista", "elemento dell'elenco", "lijstitem", "element listy", "عنصر قائمة", "פריט ברשימה"],
792 ["Menüleiste", "menu bar", "barre de menus", "barra de menús", "barra dei menu", "menubalk", "pasek menu", "شريط القوائم", "סרגל תפריטים"],
793 ["Menü", "menu", "menu", "menú", "menu", "menu", "menu", "قائمة", "תפריט"],
794 ["Menüeintrag", "menu item", "élément de menu", "elemento de menú", "voce di menu", "menu-item", "element menu", "بند قائمة", "פריט תפריט"],
795 ["Registerleiste", "page tab list", "liste d'onglets", "lista de pestañas", "elenco schede", "tabbladenlijst", "lista kart", "قائمة علامات التبويب", "רשימת כרטיסיות"],
796 ["Registerkarte", "page tab", "onglet", "pestaña", "scheda", "tabblad", "karta", "علامة تبويب", "כרטיסייה"],
797 ["Kombinationsfeld", "combo box", "zone de liste déroulante", "cuadro combinado", "casella combinata", "keuzelijst met invoervak", "pole kombi", "مربع تحرير وسرد", "תיבה משולבת"],
798 ["Grafik", "image", "image", "imagen", "immagine", "afbeelding", "obraz", "صورة", "תמונה"],
799 ["Zeichenfläche", "canvas", "zone de dessin", "lienzo", "area di disegno", "tekenvlak", "obszar rysowania", "لوحة رسم", "משטח ציור"],
800 ["Dialog", "dialog", "boîte de dialogue", "cuadro de diálogo", "finestra di dialogo", "dialoogvenster", "okno dialogowe", "مربع حوار", "תיבת דו-שיח"],
801 ["Überschrift", "heading", "titre", "encabezado", "intestazione", "kop", "nagłówek", "عنوان", "כותרת"],
802 ["Rahmen", "frame", "cadre", "marco", "cornice", "kader", "ramka", "إطار", "מסגרת"],
803 ["Anwendung", "application", "application", "aplicación", "applicazione", "toepassing", "aplikacja", "تطبيق", "יישום"],
804 ["unbekannt", "unknown", "inconnu", "desconocido", "sconosciuto", "onbekend", "nieznany", "غير معروف", "לא ידוע"],
805 ["Zeile {}: unbekannter Abschnitt [{}]", "Line {}: unknown section [{}]", "Ligne {}\u{A0}: section inconnue [{}]",
807 "Línea {}: sección desconocida [{}]", "Riga {}: sezione sconosciuta [{}]", "Regel {}: onbekende sectie [{}]",
808 "Wiersz {}: nieznana sekcja [{}]", "السطر {}: قسم غير معروف [{}]", "שורה {}: מקטע לא ידוע [{}]"],
809 ["Zeile {}: unbekannter Schlüssel „{}“ in [{}]", "Line {}: unknown key “{}” in [{}]",
810 "Ligne {}\u{A0}: clé inconnue «\u{A0}{}\u{A0}» dans [{}]", "Línea {}: clave desconocida «{}» en [{}]",
811 "Riga {}: chiave sconosciuta «{}» in [{}]", "Regel {}: onbekende sleutel ‘{}’ in [{}]", "Wiersz {}: nieznany klucz „{}” w [{}]",
812 "السطر {}: مفتاح غير معروف «{}» في [{}]", "שורה {}: מפתח לא ידוע „{}” ב-[{}]"],
813 ["Zeile {}: „{}“ steht zweimal in [{}]", "Line {}: “{}” appears twice in [{}]",
814 "Ligne {}\u{A0}: «\u{A0}{}\u{A0}» apparaît deux fois dans [{}]", "Línea {}: «{}» aparece dos veces en [{}]",
815 "Riga {}: «{}» compare due volte in [{}]", "Regel {}: ‘{}’ staat twee keer in [{}]", "Wiersz {}: „{}” występuje dwa razy w [{}]",
816 "السطر {}: «{}» مكرر في [{}]", "שורה {}: „{}” מופיע פעמיים ב-[{}]"],
817 ["Zeile {}: „Schlüssel = Wert“ erwartet", "Line {}: expected “key = value”", "Ligne {}\u{A0}: «\u{A0}clé = valeur\u{A0}» attendu",
818 "Línea {}: se esperaba «clave = valor»", "Riga {}: atteso «chiave = valore»", "Regel {}: ‘sleutel = waarde’ verwacht",
819 "Wiersz {}: oczekiwano „klucz = wartość”", "السطر {}: المتوقع «مفتاح = قيمة»", "שורה {}: נדרש „מפתח = ערך”"],
820 ["Zeile {}: „{}“ steht vor dem ersten Abschnitt", "Line {}: “{}” comes before the first section",
821 "Ligne {}\u{A0}: «\u{A0}{}\u{A0}» précède la première section", "Línea {}: «{}» está antes de la primera sección",
822 "Riga {}: «{}» precede la prima sezione", "Regel {}: ‘{}’ staat vóór de eerste sectie", "Wiersz {}: „{}” stoi przed pierwszą sekcją",
823 "السطر {}: «{}» قبل القسم الأول", "שורה {}: „{}” מופיע לפני המקטע הראשון"],
824 ["Zeile {}: „{}“ ist keine Farbe (#RRGGBB oder #AARRGGBB)", "Line {}: “{}” is not a colour (#RRGGBB or #AARRGGBB)",
825 "Ligne {}\u{A0}: «\u{A0}{}\u{A0}» n’est pas une couleur (#RRGGBB ou #AARRGGBB)", "Línea {}: «{}» no es un color (#RRGGBB o #AARRGGBB)",
826 "Riga {}: «{}» non è un colore (#RRGGBB o #AARRGGBB)", "Regel {}: ‘{}’ is geen kleur (#RRGGBB of #AARRGGBB)",
827 "Wiersz {}: „{}” nie jest kolorem (#RRGGBB lub #AARRGGBB)", "السطر {}: «{}» ليس لونًا (#RRGGBB أو #AARRGGBB)",
828 "שורה {}: „{}” אינו צבע (#RRGGBB או #AARRGGBB)"],
829 ["Zeile {}: „{}“ ist keine Zahl von {} bis {}", "Line {}: “{}” is not a number from {} to {}",
830 "Ligne {}\u{A0}: «\u{A0}{}\u{A0}» n’est pas un nombre de {} à {}", "Línea {}: «{}» no es un número de {} a {}",
831 "Riga {}: «{}» non è un numero da {} a {}", "Regel {}: ‘{}’ is geen getal van {} tot {}", "Wiersz {}: „{}” nie jest liczbą od {} do {}",
832 "السطر {}: «{}» ليس رقمًا من {} إلى {}", "שורה {}: „{}” אינו מספר בין {} ל-{}"],
833 ["Zeile {}: „{}“ ist keine Schriftstärke (regular, semibold, bold, 100 bis 900)",
834 "Line {}: “{}” is not a font weight (regular, semibold, bold, 100 to 900)",
835 "Ligne {}\u{A0}: «\u{A0}{}\u{A0}» n’est pas une graisse (regular, semibold, bold, 100 à 900)",
836 "Línea {}: «{}» no es un grosor de fuente (regular, semibold, bold, 100 a 900)",
837 "Riga {}: «{}» non è uno spessore del carattere (regular, semibold, bold, da 100 a 900)",
838 "Regel {}: ‘{}’ is geen letterdikte (regular, semibold, bold, 100 tot 900)",
839 "Wiersz {}: „{}” nie jest grubością czcionki (regular, semibold, bold, 100 do 900)",
840 "السطر {}: «{}» ليس سُمك خط (regular أو semibold أو bold أو 100 إلى 900)",
841 "שורה {}: „{}” אינו משקל גופן (regular, semibold, bold, 100 עד 900)"],
842 ["Theme-Datei nicht lesbar: {}", "Theme file not readable: {}", "Fichier de thème illisible\u{A0}: {}",
843 "No se puede leer el archivo de tema: {}", "File del tema non leggibile: {}", "Themabestand niet leesbaar: {}",
844 "Nie można odczytać pliku motywu: {}", "تعذرت قراءة ملف السمة: {}", "לא ניתן לקרוא את קובץ ערכת הנושא: {}"],
845 ["Zeile {}: „{}“ sind keine Achsenwerte (wght=650, wdth=87.5 …)",
846 "Line {}: “{}” are no axis values (wght=650, wdth=87.5 …)",
847 "Ligne {}\u{A0}: «\u{A0}{}\u{A0}» ne sont pas des valeurs d’axes (wght=650, wdth=87.5 …)",
848 "Línea {}: «{}» no son valores de ejes (wght=650, wdth=87.5 …)",
849 "Riga {}: «{}» non sono valori di assi (wght=650, wdth=87.5 …)",
850 "Regel {}: ‘{}’ zijn geen aswaarden (wght=650, wdth=87.5 …)",
851 "Wiersz {}: „{}” to nie wartości osi (wght=650, wdth=87.5 …)",
852 "السطر {}: «{}» ليست قيم محاور (wght=650، wdth=87.5 …)",
853 "שורה {}: „{}” אינם ערכי צירים (wght=650, wdth=87.5 …)"],
854 ["Schrift nicht ladbar: {}", "Font cannot be loaded: {}", "Police impossible à charger\u{A0}: {}",
855 "No se puede cargar la fuente: {}", "Impossibile caricare il carattere: {}", "Lettertype kan niet worden geladen: {}",
856 "Nie można wczytać czcionki: {}", "تعذر تحميل الخط: {}", "לא ניתן לטעון את הגופן: {}"],
857 ["Minimieren", "Minimize", "Réduire", "Minimizar", "Riduci a icona", "Minimaliseren", "Minimalizuj", "تصغير", "מזעור"],
859 ["Maximieren", "Maximize", "Agrandir", "Maximizar", "Ingrandisci", "Maximaliseren", "Maksymalizuj", "تكبير", "הגדלה"],
860 ["Wiederherstellen", "Restore", "Restaurer", "Restaurar", "Ripristina", "Herstellen", "Przywróć", "استعادة", "שחזור"],
861 ["minimiert", "minimized", "réduite", "minimizada", "ridotta a icona", "geminimaliseerd", "zminimalizowane", "مصغّرة", "ממוזער"],
862 ["maximiert", "maximized", "agrandie", "maximizada", "ingrandita", "gemaximaliseerd", "zmaksymalizowane", "مكبّرة", "מוגדל"],
863 ["Taskleiste", "Taskbar", "Barre des tâches", "Barra de tareas", "Barra delle applicazioni", "Taakbalk", "Pasek zadań", "شريط المهام", "שורת המשימות"],
864 ["Weitere Fenster", "More windows", "Plus de fenêtres", "Más ventanas", "Altre finestre", "Meer vensters", "Więcej okien", "مزيد من النوافذ", "חלונות נוספים"],
865 ["Vervollständigen", "Complete", "Compléter", "Completar", "Completa", "Aanvullen", "Uzupełnij", "إكمال", "השלמה"],
867 ["Vorschläge", "Suggestions", "Suggestions", "Sugerencias", "Suggerimenti", "Suggesties", "Podpowiedzi", "اقتراحات", "הצעות"],
868];
869
870pub fn tr(de: &'static str) -> &'static str {
873 let l = li();
874 if l == 0 {
875 return de;
876 }
877 LIB_TEXTS.iter().find(|r| r[0] == de).map_or(de, |r| r[l])
878}
879
880pub fn library_languages() -> &'static [&'static str] {
883 &LIB_LANGS
884}
885
886pub fn library_keys() -> impl Iterator<Item = &'static str> {
888 LIB_TEXTS.iter().map(|r| r[0])
889}
890
891static MONTHS: [[&str; 12]; 9] = [
894 ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
895 ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
896 ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
897 ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
898 ["gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"],
899 ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
900 ["styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"],
901 ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
902 ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
903];
904static MONTHS_SHORT: [[&str; 12]; 9] = [
905 ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
906 ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
907 ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."],
908 ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic"],
909 ["gen", "feb", "mar", "apr", "mag", "giu", "lug", "ago", "set", "ott", "nov", "dic"],
910 ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
911 ["sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paź", "lis", "gru"],
912 ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
913 ["ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳"],
914];
915static WEEKDAYS_SHORT: [[&str; 7]; 9] = [
917 ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
918 ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
919 ["lu", "ma", "me", "je", "ve", "sa", "di"],
920 ["lu", "ma", "mi", "ju", "vi", "sá", "do"],
921 ["lu", "ma", "me", "gi", "ve", "sa", "do"],
922 ["ma", "di", "wo", "do", "vr", "za", "zo"],
923 ["pn", "wt", "śr", "cz", "pt", "so", "nd"],
924 ["ن", "ث", "ر", "خ", "ج", "س", "ح"],
925 ["ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳", "א׳"],
926];
927static WEEKDAYS_ABBR: [[&str; 7]; 9] = [
928 ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
929 ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
930 ["lun.", "mar.", "mer.", "jeu.", "ven.", "sam.", "dim."],
931 ["lun", "mar", "mié", "jue", "vie", "sáb", "dom"],
932 ["lun", "mar", "mer", "gio", "ven", "sab", "dom"],
933 ["ma", "di", "wo", "do", "vr", "za", "zo"],
934 ["pon.", "wt.", "śr.", "czw.", "pt.", "sob.", "niedz."],
935 ["الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
936 ["יום ב׳", "יום ג׳", "יום ד׳", "יום ה׳", "יום ו׳", "שבת", "יום א׳"],
937];
938
939fn li() -> usize {
940 LIB.load(Ordering::Relaxed) as usize
941}
942
943pub fn month_name(m: u32) -> &'static str {
945 MONTHS[li()][((m.max(1) - 1) % 12) as usize]
946}
947
948pub fn month_short(m: u32) -> &'static str {
950 MONTHS_SHORT[li()][((m.max(1) - 1) % 12) as usize]
951}
952
953pub fn weekday_short(d: u32) -> &'static str {
955 WEEKDAYS_SHORT[li()][(d % 7) as usize]
956}
957
958pub fn weekday_abbr(d: u32) -> &'static str {
960 WEEKDAYS_ABBR[li()][(d % 7) as usize]
961}
962
963pub struct Catalog {
965 langs: Vec<String>,
966 rows: BTreeMap<&'static str, Vec<&'static str>>,
967}
968
969impl Catalog {
970 pub fn from_tsv(text: &'static str) -> Catalog {
973 let mut lines = text.lines();
974 let langs: Vec<String> = lines.next().map(|h| h.split('\t').map(|s| String::from(s.trim())).collect()).unwrap_or_default();
975 let mut rows = BTreeMap::new();
976 for line in lines {
977 if line.is_empty() || line.starts_with('#') {
978 continue;
979 }
980 let mut cols = line.split('\t');
981 let Some(key) = cols.next() else { continue };
982 let rest: Vec<&'static str> = cols.collect();
983 rows.insert(key, rest);
984 }
985 Catalog { langs, rows }
986 }
987
988 pub fn with_library_languages(mut self) -> Catalog {
993 for l in LIB_LANGS {
994 let no_font = cfg!(target_arch = "wasm32") && matches!(l, "ar" | "he");
995 if !no_font && !self.langs.iter().any(|c| c == l) {
996 self.langs.push(String::from(l));
997 }
998 }
999 self
1000 }
1001
1002 pub fn languages(&self) -> &[String] {
1004 &self.langs
1005 }
1006
1007 pub fn tr<'a>(&'a self, s: &'a str) -> &'a str {
1009 let l = language() as usize;
1010 if l == 0 {
1011 return s;
1012 }
1013 match self.rows.get(s).and_then(|r| r.get(l - 1)) {
1014 Some(t) if !t.is_empty() => t,
1015 _ => s,
1016 }
1017 }
1018
1019 pub fn has(&self, s: &str) -> bool {
1021 self.rows.contains_key(s)
1022 }
1023}
1024
1025static APP: rt::sync::SpinLock<Option<&'static Catalog>> = rt::sync::SpinLock::new(None);
1026
1027pub fn set_catalog(c: Catalog) {
1031 let r: &'static Catalog = Box::leak(Box::new(c));
1032 *APP.lock() = Some(r);
1033 let code = EXPLICIT_CODE.lock().clone();
1034 if let Some(code) = code {
1035 select(pick(&[code]));
1036 } else if EXPLICIT.load(Ordering::Relaxed) {
1037 select(language());
1038 } else {
1039 select(pick(&user_languages()));
1040 }
1041}
1042
1043pub fn t(s: &'static str) -> &'static str {
1046 if language() == LANG_DE {
1047 return s;
1048 }
1049 let cat = *APP.lock();
1050 if let Some(x) = cat.and_then(|c| c.get_static(s)) {
1051 return x;
1052 }
1053 let lib = tr(s);
1054 if !core::ptr::eq(lib, s) {
1055 return lib;
1056 }
1057 cat.and_then(|c| c.english(s)).unwrap_or(s)
1058}
1059
1060static COMMANDS: rt::sync::SpinLock<Vec<(usize, u32, &'static [Command])>> = rt::sync::SpinLock::new(Vec::new());
1062static MENUS: rt::sync::SpinLock<Vec<(usize, u32, &'static [Mi])>> = rt::sync::SpinLock::new(Vec::new());
1063
1064pub fn commands(src: &'static [Command]) -> &'static [Command] {
1066 let l = language();
1067 if l == LANG_DE || src.is_empty() {
1068 return src;
1069 }
1070 let key = src.as_ptr() as usize;
1071 if let Some(&(_, _, done)) = COMMANDS.lock().iter().find(|e| e.0 == key && e.1 == l) {
1072 return done;
1073 }
1074 let done: &'static [Command] = Vec::leak(src.iter().map(|c| Command { label: t(c.label), ..*c }).collect());
1075 COMMANDS.lock().push((key, l, done));
1076 done
1077}
1078
1079pub fn menu(src: &'static [Mi]) -> &'static [Mi] {
1081 let l = language();
1082 if l == LANG_DE || src.is_empty() {
1083 return src;
1084 }
1085 let key = src.as_ptr() as usize;
1086 if let Some(&(_, _, done)) = MENUS.lock().iter().find(|e| e.0 == key && e.1 == l) {
1087 return done;
1088 }
1089 let v: Vec<Mi> = src
1090 .iter()
1091 .map(|it| match *it {
1092 Mi::Menu(label, sub) => Mi::Menu(t(label), menu(sub)),
1093 Mi::Sub(label, sub) => Mi::Sub(t(label), menu(sub)),
1094 Mi::Item(id, label, icon) => Mi::Item(id, t(label), icon),
1095 Mi::List(id, n, label) => Mi::List(id, n, t(label)),
1096 other => other,
1097 })
1098 .collect();
1099 let done: &'static [Mi] = Vec::leak(v);
1100 MENUS.lock().push((key, l, done));
1101 done
1102}
1103
1104pub(crate) fn t_text(s: &str) -> String {
1107 let cat = if language() == LANG_DE { None } else { *APP.lock() };
1108 String::from(cat.and_then(|c| c.get_static(s).or_else(|| c.english(s))).unwrap_or(s))
1109}
1110
1111pub fn tf(s: &'static str, args: &[&str]) -> String {
1113 fill(t(s), args)
1114}
1115
1116pub fn list(items: &[&'static str]) -> Vec<&'static str> {
1118 items.iter().map(|s| t(s)).collect()
1119}
1120
1121pub fn fill(text: &str, args: &[&str]) -> String {
1123 let mut out = String::with_capacity(text.len() + 16);
1124 let mut rest = text;
1125 let mut i = 0;
1126 while let Some(p) = rest.find("{}") {
1127 out.push_str(&rest[..p]);
1128 out.push_str(args.get(i).copied().unwrap_or(""));
1129 i += 1;
1130 rest = &rest[p + 2..];
1131 }
1132 out.push_str(rest);
1133 out
1134}
1135
1136impl Catalog {
1137 pub fn get_static(&self, s: &str) -> Option<&'static str> {
1139 let l = language() as usize;
1140 if l == 0 {
1141 return None;
1142 }
1143 self.rows.get(s).and_then(|r| r.get(l - 1)).copied().filter(|t| !t.is_empty())
1144 }
1145
1146 fn english(&self, s: &str) -> Option<&'static str> {
1148 let k = self.langs.iter().position(|c| c == "en").filter(|k| *k > 0)?;
1149 self.rows.get(s).and_then(|r| r.get(k - 1)).copied().filter(|t| !t.is_empty())
1150 }
1151}