diff --git a/docs/native-vs-web.md b/docs/native-vs-web.md index 90b88a0de..6a91f39e6 100644 --- a/docs/native-vs-web.md +++ b/docs/native-vs-web.md @@ -76,7 +76,7 @@ shared: native renders the same modals too, so the desktop is effectively single-window now. A modal's backdrop dims and blocks clicks but does not dismiss; the ✕ button closes it. -### Parallelism — web: single-threaded +### Parallelism — web: main thread plus one parse/serialize worker `wasm32` has no threads without SharedArrayBuffer (which needs COOP/COEP headers GitHub Pages can't set). `crate::par::prelude` re-exports `rayon` on native and sequential `std` iterators on wasm, so the same call sites run in diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 079f34725..44447193d 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -3584,6 +3584,7 @@ view = .opening-ocs-discussions-for-help-and-questions = يجري فتح مناقشات OCS للمساعدة والأسئلة... .opening-ocs-web = يجري فتح OCS Web... .opening-the-command-reference = فتح مرجع الأوامر... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" محمّل بالفعل بمحتوى مختلف؛ تم الاحتفاظ بالملف الموجود. .opening-patreon-page = يجري فتح صفحة Patreon... .opening-feedback-page = يجري فتح صفحة الملاحظات... .opening-release-notes = يجري فتح ملاحظات الإصدار... diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 1bb25ed04..20deec855 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -3571,6 +3571,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Отваряне на OCS дискусии за помощ и въпроси... .opening-ocs-web = Отваряне на OCS уебсайта... .opening-the-command-reference = Отваряне на справочника за команди... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" вече е зареден с различно съдържание; съществуващият файл е запазен. .opening-patreon-page = Отваряне на страницата в Patreon... .opening-feedback-page = Отваряне на страницата за обратна връзка... .opening-release-notes = Отваряне на бележките по версията... diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index 63eacc3be..24fe5dbab 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -3569,6 +3569,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Otevírání diskuzí OCS pro nápovědu a dotazy... .opening-ocs-web = Otevírání webu OCS... .opening-the-command-reference = Otevírání referenční příručky příkazů... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" je již načten s jiným obsahem; existující soubor byl zachován. .opening-patreon-page = Otevírání stránky Patreon... .opening-feedback-page = Otevírá se stránka zpětné vazby... .opening-release-notes = Otevírání poznámek k vydání... diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index b06c24314..974a876b9 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -3570,6 +3570,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Eröffnung OCS Diskussionen für Hilfe und Fragen... .opening-ocs-web = Öffnen OCS Web... .opening-the-command-reference = Öffnen der Befehlsreferenz... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" ist bereits mit anderem Inhalt geladen; die vorhandene Datei wurde behalten. .opening-patreon-page = Eröffnungsseite Patreon... .opening-feedback-page = Feedbackseite öffnen... .opening-release-notes = Opening Release Notes... diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 1b8c28c9d..446a67c01 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -3566,6 +3566,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Άνοιγμα των συζητήσεων OCS για βοήθεια και ερωτήσεις... .opening-ocs-web = Άνοιγμα του OCS Web... .opening-the-command-reference = Άνοιγμα της αναφοράς εντολών... + .already-loaded-different-contents-kept = Το "__ocs_fmt_0__" είναι ήδη φορτωμένο με διαφορετικό περιεχόμενο· διατηρήθηκε το υπάρχον αρχείο. .opening-patreon-page = Άνοιγμα της σελίδας Patreon... .opening-feedback-page = Άνοιγμα της σελίδας σχολίων... .opening-release-notes = Άνοιγμα των σημειώσεων έκδοσης... diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index db51181f5..838c2714c 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -3567,6 +3567,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Opening OCS Discussions for help and questions... .opening-ocs-web = Opening OCS Web... .opening-the-command-reference = Opening the command reference... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" is already loaded with different contents; the existing file was kept. .opening-patreon-page = Opening Patreon page... .opening-feedback-page = Opening feedback page... .opening-release-notes = Opening release notes... diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 777aa674a..8103840dc 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -3572,6 +3572,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Abriendo Debates de OCS para obtener ayuda y hacer preguntas... .opening-ocs-web = Abriendo OCS Web... .opening-the-command-reference = Abriendo la referencia de comandos... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" ya está cargado con contenido diferente; se conservó el archivo existente. .opening-patreon-page = Abriendo la página de Patreon... .opening-feedback-page = Abriendo la página de comentarios... .opening-release-notes = Abriendo las notas de la versión... diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 7d12acc2f..c91c23785 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -3571,6 +3571,7 @@ view = .opening-ocs-discussions-for-help-and-questions = OCS-keskustelujen avaaminen apua ja kysymyksiä varten... .opening-ocs-web = Avataan OCS Web... .opening-the-command-reference = Avataan komentoviittausta... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" on jo ladattu eri sisällöllä; olemassa oleva tiedosto säilytettiin. .opening-patreon-page = Avataan Patreon-sivua... .opening-feedback-page = Palautesivua avataan... .opening-release-notes = Avataan julkaisutietoja... diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 40c9b0dc0..becf3e8d9 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -3572,6 +3572,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Ouverture OCS Discussions pour l'aide et les questions... .opening-ocs-web = Ouverture du site Web OCS... .opening-the-command-reference = Ouverture de la référence des commandes... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" est déjà chargé avec un contenu différent ; le fichier existant a été conservé. .opening-patreon-page = Ouverture de la page Patreon... .opening-feedback-page = Ouverture de la page de rétroaction... .opening-release-notes = Ouverture des notes de sortie... diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 96c6f7f7e..11b9dbc7a 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -3560,6 +3560,7 @@ view = .opening-ocs-discussions-for-help-and-questions = OCS मदद और प्रश्नों के लिए चर्चा खोलना। .opening-ocs-web = OCS वेब खोलना ... .opening-the-command-reference = कमांड संदर्भ खोला जा रहा है... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" अलग सामग्री के साथ पहले से लोड है; मौजूदा फ़ाइल रखी गई। .opening-patreon-page = Patreon पृष्ठ खोला जा रहा है… .opening-feedback-page = प्रतिक्रिया पृष्ठ खोलना .opening-release-notes = रिलीज नोट्स खोलना ... diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 46235c51d..713915321 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -3571,6 +3571,7 @@ view = .opening-ocs-discussions-for-help-and-questions = A OCS beszélgetések megnyitása segítségért és kérdésekért... .opening-ocs-web = A OCS web megnyitása... .opening-the-command-reference = A parancsreferencia megnyitása... + .already-loaded-different-contents-kept = A(z) "__ocs_fmt_0__" már betöltve eltérő tartalommal; a meglévő fájl megőrizve. .opening-patreon-page = Patreon oldal megnyitása... .opening-feedback-page = Visszajelzési oldal megnyitása... .opening-release-notes = Kiadási megjegyzések megnyitása... diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 5f64f3020..ebbfdedde 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -3571,6 +3571,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Apertura delle discussioni OCS per assistenza e domande... .opening-ocs-web = Apertura del Web OCS... .opening-the-command-reference = Apertura del riferimento dei comandi... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" è già caricato con contenuti diversi; il file esistente è stato mantenuto. .opening-patreon-page = Apertura della pagina Patreon... .opening-feedback-page = Apertura della pagina di feedback... .opening-release-notes = Note sulla versione di apertura... diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 1151a0476..51d99e85b 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -3560,6 +3560,7 @@ view = .opening-ocs-discussions-for-help-and-questions = ヘルプと質問のため OCS ディスカッションを開いています... .opening-ocs-web = OCS Web を開いています... .opening-the-command-reference = コマンドリファレンスを開いています... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" は既に別の内容で読み込まれています。既存のファイルを保持しました。 .opening-patreon-page = Patreon ページを開いています... .opening-feedback-page = フィードバックページを開いています... .opening-release-notes = リリースノートを開いています... diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 29348e8bf..8efcb0c7e 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -3571,6 +3571,7 @@ view = .opening-ocs-discussions-for-help-and-questions = OCS 열기 도움말 및 질문에 대한 토론... .opening-ocs-web = OCS 웹을 여는 중... .opening-the-command-reference = 명령 참조 열기... + .already-loaded-different-contents-kept = "__ocs_fmt_0__"이(가) 이미 다른 내용으로 로드되었습니다. 기존 파일을 유지했습니다. .opening-patreon-page = Patreon 페이지를 여는 중... .opening-feedback-page = 피드백 페이지를 여는 중... .opening-release-notes = 출시 노트를 여는 중... diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index d37495e40..8825a4a3e 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -3570,6 +3570,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Openen OCS Discussie voor hulp en vragen... .opening-ocs-web = Openen OCS Web... .opening-the-command-reference = Commandoreferentie openen... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" is al geladen met andere inhoud; het bestaande bestand is bewaard. .opening-patreon-page = Patreon pagina openen... .opening-feedback-page = Herinneringspagina openen... .opening-release-notes = Openen van de release notes... diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index dd046d9ca..a2543d47d 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -3571,6 +3571,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Otwieranie dyskusji OCS w celu uzyskania pomocy i pytań... .opening-ocs-web = Otwieranie OCS Web... .opening-the-command-reference = Otwieranie dokumentacji poleceń... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" jest już wczytany z inną zawartością; zachowano istniejący plik. .opening-patreon-page = Otwieranie strony Patreon... .opening-feedback-page = Otwieram stronę z opiniami... .opening-release-notes = Otwieram informacje o wersji... diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index 471882316..714d2cb27 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -3572,6 +3572,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Abrindo Discussões do OCS para ajuda e perguntas... .opening-ocs-web = Abrindo OCS Web... .opening-the-command-reference = Abrindo a referência de comandos... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" já está carregado com conteúdo diferente; o ficheiro existente foi mantido. .opening-patreon-page = Abrindo página do Patreon... .opening-feedback-page = Abrindo página de comentários... .opening-release-notes = Abrindo notas da versão... diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 6ad61985b..ebd46c550 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -3573,6 +3573,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Открытие OCS Дискуссии о помощи и вопросах .opening-ocs-web = Открытие OCS Веб-сайт .opening-the-command-reference = Открытие справочника команд... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" уже загружен с другим содержимым; существующий файл сохранён. .opening-patreon-page = Открытие страницы Patreon... .opening-feedback-page = Открываем страницу обратной связи... .opening-release-notes = Открытие выпускных заметок... diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index d0a8bf12f..039b9744a 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -3522,6 +3522,7 @@ view = .opening-ocs-discussions-for-help-and-questions = Yardım ve sorular için OCS Tartışmaları açılıyor... .opening-ocs-web = OCS Web açılıyor... .opening-the-command-reference = Komut başvurusu açılıyor... + .already-loaded-different-contents-kept = "__ocs_fmt_0__" zaten farklı içerikle yüklü; mevcut dosya tutuldu. .opening-patreon-page = Patreon sayfası açılıyor... .opening-feedback-page = Geri bildirim sayfası açılıyor... .opening-release-notes = Sürüm notları açılıyor... diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index 12eedff9d..ccbae3d93 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -3555,6 +3555,7 @@ view = .opening-ocs-discussions-for-help-and-questions = 开幕OCS 讨论帮助和问题... .opening-ocs-web = 打开OCS网络... .opening-the-command-reference = 正在打开命令参考... + .already-loaded-different-contents-kept = "__ocs_fmt_0__"已以不同内容加载;保留了现有文件。 .opening-patreon-page = 打开帕特伦的页面... .opening-feedback-page = 打开反馈页面... .opening-release-notes = 打开发行笔记... diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 9ad2d8bf7..64446ac4b 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -3567,6 +3567,7 @@ view = .opening-ocs-discussions-for-help-and-questions = 開幕OCS 討論幫助和問題... .opening-ocs-web = 開啟OCS網路... .opening-the-command-reference = 正在開啟命令參考... + .already-loaded-different-contents-kept = "__ocs_fmt_0__"已以不同內容載入;保留了現有檔案。 .opening-patreon-page = 開啟帕特倫的頁面... .opening-feedback-page = 開啟反饋頁面... .opening-release-notes = 開啟發行筆記... diff --git a/src/app/annotation_data.rs b/src/app/annotation_data.rs index aed354797..997dd0465 100644 --- a/src/app/annotation_data.rs +++ b/src/app/annotation_data.rs @@ -1589,6 +1589,16 @@ impl OpenCADStudio { .pick_files() .await .unwrap_or_default(); + // Each picked file becomes a full parsed document held in + // the registry for the session; a bound keeps a giant + // multi-pick from exhausting the wasm heap (tab death). + const MAX_EXTRACTION_SOURCES: usize = 16; + if handles.len() > MAX_EXTRACTION_SOURCES { + return Err(crate::tf!( + "At most {MAX_EXTRACTION_SOURCES} drawings can be added in the browser." + ) + .into_owned()); + } let mut paths = Vec::new(); for handle in handles { let name = handle.file_name(); diff --git a/src/app/update/file.rs b/src/app/update/file.rs index aac1f0a66..e422ee380 100644 --- a/src/app/update/file.rs +++ b/src/app/update/file.rs @@ -2283,6 +2283,13 @@ impl OpenCADStudio { } return self.continue_tab_close_queue(); } + } else if matches!(self.pending_close, Some(crate::app::PendingClose::Quit)) { + // Mirror the native Quit continuation: offer to save the + // next dirty tab, or finish the quit. + if self.tabs.iter().any(|tab| tab.dirty) { + return self.open_unsaved_dialog_window(); + } + return Task::batch([self.close_unsaved_dialog_window(), self.exit_app()]); } else if self.pending_close.is_some() { return self.open_unsaved_dialog_window(); } diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index 97fc3795c..319d66d4a 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -572,6 +572,16 @@ impl OpenCADStudio { .file_name() .map(|name| name.to_string_lossy().into_owned()) .unwrap_or_else(|| path.to_string_lossy().into_owned()); + // The start page stays clickable under the open overlay, + // so a recent can race an in-flight open and clobber it + // (its WebFileOpened then fails the id check and the + // bytes are lost) — refuse like on_open_file does. + if self.opening.is_some() { + self.command_line.push_info( + crate::t!("An open is already in progress.").as_ref(), + ); + return Task::none(); + } let state = std::sync::Arc::new(crate::io::OpenProgressState::new( crate::app::OPEN_PHASE_READING, )); diff --git a/src/io/web_drop.rs b/src/io/web_drop.rs index 5fa8402c5..1f6ac571b 100644 --- a/src/io/web_drop.rs +++ b/src/io/web_drop.rs @@ -290,3 +290,20 @@ fn is_image_name(name: &str) -> bool { "png" | "jpg" | "jpeg" | "bmp" | "tiff" | "tif" ) } + +#[cfg(test)] +mod tests { + use super::is_drawing_name; + + #[test] + fn drawing_names_use_the_worker_convention() { + assert!(is_drawing_name("plan.dwg")); + assert!(is_drawing_name("PLAN.DXF")); + assert!(is_drawing_name("DWG")); + assert!(is_drawing_name("dxf")); + assert!(!is_drawing_name("plan.png")); + assert!(!is_drawing_name("dwgx")); + assert!(!is_drawing_name("plan.dwg.txt")); + assert!(!is_drawing_name("")); + } +} diff --git a/src/io/web_recent.rs b/src/io/web_recent.rs index ffa93bef1..c3aaa64bb 100644 --- a/src/io/web_recent.rs +++ b/src/io/web_recent.rs @@ -312,3 +312,23 @@ pub(crate) async fn modified_ms(name: &str) -> Option { .ok()?; Some(file.last_modified()) } + +#[cfg(test)] +mod tests { + use super::name_hash; + + /// Canonical FNV-1a 64 over the raw name bytes — the reference vector + /// from the spec's test suite. + #[test] + fn name_hash_is_fnv1a64() { + assert_eq!(name_hash(""), "cbf29ce484222325"); + assert_eq!(name_hash("a"), "af63dc4c8601ec8c"); + assert_eq!(name_hash("foobar"), "85944171f73967e8"); + } + + #[test] + fn name_hash_distinguishes_case_and_extension() { + assert_ne!(name_hash("a.dwg"), name_hash("A.dwg")); + assert_ne!(name_hash("a.dwg"), name_hash("a.dxf")); + } +} diff --git a/src/io/xref.rs b/src/io/xref.rs index 1b8c2c851..d39bcb979 100644 --- a/src/io/xref.rs +++ b/src/io/xref.rs @@ -790,6 +790,17 @@ fn set_handle(entity: &mut EntityType, h: Handle) { mod tests { use super::*; + /// The registries are process-global and the default harness runs tests + /// in parallel; the eviction test's inserts can evict a sibling test's + /// entry mid-assert. Registry tests hold this lock for their duration. + fn registry_guard() -> std::sync::MutexGuard<'static, ()> { + static LOCK: OnceLock> = OnceLock::new(); + LOCK.get_or_init(|| Mutex::new(())) + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()) + } + + fn outcome() -> acadrust::ReadOutcome { acadrust::ReadOutcome::new(CadDocument::new(), acadrust::ReadStats::default()) } @@ -821,6 +832,7 @@ mod tests { #[test] fn registry_finds_a_registered_source_by_trailing_name() { + let _registry = registry_guard(); let registered = "Registry-Find-Site.dwg"; register_source(registered, Arc::new(vec![1, 2, 3])); // The drawing's stored path is the author's absolute foreign path; @@ -840,6 +852,7 @@ mod tests { /// re-registration of a live name neither evicts nor duplicates it. #[test] fn source_registry_evicts_oldest_beyond_the_cap() { + let _registry = registry_guard(); for i in 0..(SOURCE_CAP + 2) { register_source(&format!("f{i}.dwg"), Arc::new(vec![i as u8])); } @@ -879,6 +892,7 @@ mod tests { #[test] fn register_source_supersedes_a_cached_parse_of_the_same_file() { + let _registry = registry_guard(); let name = "Registry-Supersede-Plan.dwg"; register_parsed(name, outcome()); // Re-registering the same file under a differently-cased path name diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index f3a829579..6672a517e 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -1885,6 +1885,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "Opening OCS Discussions for help and questions..." => Some(("view", "opening-ocs-discussions-for-help-and-questions")), "Opening OCS Web..." => Some(("view", "opening-ocs-web")), "Opening the command reference..." => Some(("view", "opening-the-command-reference")), + "\"{name}\" is already loaded with different contents; the existing file was kept." => Some(("file", "already-loaded-different-contents-kept")), "Opening Patreon page..." => Some(("view", "opening-patreon-page")), "Opening feedback page..." => Some(("view", "opening-feedback-page")), "Opening file" => Some(("ui", "opening-file")),