From 8102e9e6e831c6f8fa55992e236bd6e25e4b472c Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Wed, 11 Nov 2026 11:41:02 -0800 Subject: [PATCH] i18n: plug-in limit messages are translated in every complete-message catalog The instruction, time and memory budgets and the output size a plug-in run can exceed had @msg rows only in hi and sv. Every other complete-message catalog now has them, next to the other plug-in budget rows, and every complete-message catalog has a row for the error of a plug-in removal that leaves the plug-in's grant in the plug-in store. The message scan now reads a message that an error or a status takes from a &str constant (Error::Limit(TIME_BUDGET.into()), crate::runtime::SELECTION_TOO_LARGE), so the untranslated-strings report lists such messages. Tests: message_scan_reads_messages_held_in_constants and plugin_limit_errors_are_translated. --- crates/ui-egui/src/i18n/ca.tsv | 5 + crates/ui-egui/src/i18n/cs.tsv | 5 + crates/ui-egui/src/i18n/de.tsv | 5 + crates/ui-egui/src/i18n/el.tsv | 5 + crates/ui-egui/src/i18n/es.tsv | 5 + crates/ui-egui/src/i18n/fi.tsv | 5 + crates/ui-egui/src/i18n/fr.tsv | 5 + crates/ui-egui/src/i18n/hi.tsv | 1 + crates/ui-egui/src/i18n/hu.tsv | 5 + crates/ui-egui/src/i18n/it.tsv | 5 + crates/ui-egui/src/i18n/ja.tsv | 5 + crates/ui-egui/src/i18n/ka.tsv | 5 + crates/ui-egui/src/i18n/ko.tsv | 5 + crates/ui-egui/src/i18n/pl.tsv | 5 + crates/ui-egui/src/i18n/pt-br.tsv | 5 + crates/ui-egui/src/i18n/ru.tsv | 5 + crates/ui-egui/src/i18n/sv.tsv | 1 + crates/ui-egui/src/i18n/tests.rs | 137 +++++++++++++++++++++++++--- crates/ui-egui/src/i18n/tr.tsv | 5 + crates/ui-egui/src/i18n/uk.tsv | 5 + crates/ui-egui/src/i18n/vi.tsv | 5 + crates/ui-egui/src/i18n/zh-hans.tsv | 5 + crates/ui-egui/src/i18n/zh-hant.tsv | 5 + docs/target-app-parity.md | 1 + 24 files changed, 229 insertions(+), 11 deletions(-) diff --git a/crates/ui-egui/src/i18n/ca.tsv b/crates/ui-egui/src/i18n/ca.tsv index 4af431332..63c7221bc 100644 --- a/crates/ui-egui/src/i18n/ca.tsv +++ b/crates/ui-egui/src/i18n/ca.tsv @@ -6093,6 +6093,11 @@ digits Malayalam Malaiàlam @msg `inputs` needs the permission `doc.read` `inputs` requereix el permís `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) pressupost de memòria (l’objecte {_1} necessita {size} bytes d’entrada, en queden {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) pressupost d’objectes (més de {MAX_OBJECTS} objectes de només lectura) +@msg instruction budget pressupost d’instruccions +@msg time budget pressupost de temps +@msg memory budget (the selection is too large to hand over) pressupost de memòria (la selecció és massa gran per passar-la) +@msg output size ({what} is {len} bytes, limit {max}) mida de la sortida ({what} fa {len} bytes, límit {max}) +@msg the plug-in's grant can't be removed from the plug-in store el permís del complement no es pot treure del magatzem de complements @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it el permís `{shown}` està reservat per a una API de complements posterior; aquest amfitrió no el concedeix @msg unknown permission `{shown}` permís desconegut `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants «{name}» demana els permisos {asked}: una persona els ha d’aprovar a l’aplicació d’escriptori, o passa `grant` en una sessió iniciada amb --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 821d4a90c..adffc014c 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -6056,6 +6056,11 @@ axis Y Axis osa Y @msg `inputs` needs the permission `doc.read` `inputs` vyžaduje oprávnění `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) rozpočet paměti (objekt {_1} potřebuje {size} bajtů vstupu, zbývá {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) rozpočet objektů (více než {MAX_OBJECTS} objektů jen pro čtení) +@msg instruction budget rozpočet instrukcí +@msg time budget časový rozpočet +@msg memory budget (the selection is too large to hand over) rozpočet paměti (výběr je příliš velký na předání) +@msg output size ({what} is {len} bytes, limit {max}) velikost výstupu ({what} má {len} bajtů, limit {max}) +@msg the plug-in's grant can't be removed from the plug-in store oprávnění zásuvného modulu nelze odebrat z úložiště zásuvných modulů @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it oprávnění `{shown}` je vyhrazeno pro pozdější API zásuvných modulů; tento hostitel ho neuděluje @msg unknown permission `{shown}` neznámé oprávnění `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants „{name}“ žádá o oprávnění {asked}: musí je schválit člověk v desktopové aplikaci, nebo předejte `grant` v relaci spuštěné s --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index f7bc97c90..83ef9bb91 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -5639,6 +5639,11 @@ axis Y Axis Y-Achse @msg `inputs` needs the permission `doc.read` `inputs` erfordert die Berechtigung `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) Speicherbudget (Objekt {_1} benötigt {size} Byte Eingabe, {left} verbleiben) @msg object budget (more than {MAX_OBJECTS} read-only objects) Objektbudget (mehr als {MAX_OBJECTS} schreibgeschützte Objekte) +@msg instruction budget Anweisungsbudget +@msg time budget Zeitbudget +@msg memory budget (the selection is too large to hand over) Speicherbudget (die Auswahl ist zu groß zum Übergeben) +@msg output size ({what} is {len} bytes, limit {max}) Ausgabegröße ({what} ist {len} Byte groß, Grenze {max}) +@msg the plug-in's grant can't be removed from the plug-in store die Berechtigung des Plug-ins kann nicht aus dem Plug-in-Speicher entfernt werden @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it die Berechtigung `{shown}` ist für eine spätere Plug-in-API reserviert; dieser Host gewährt sie nicht @msg unknown permission `{shown}` unbekannte Berechtigung `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants „{name}“ verlangt die Berechtigungen {asked}: Eine Person muss sie in der Desktop-App genehmigen, oder übergeben Sie `grant` in einer mit --allow-plugin-grants gestarteten Sitzung diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index e1189bc98..a06f21d46 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -6007,6 +6007,11 @@ axis Y Axis Άξονας Y @msg `inputs` needs the permission `doc.read` το `inputs` απαιτεί το δικαίωμα `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) προϋπολογισμός μνήμης (το αντικείμενο {_1} χρειάζεται {size} byte εισόδου, απομένουν {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) προϋπολογισμός αντικειμένων (περισσότερα από {MAX_OBJECTS} αντικείμενα μόνο για ανάγνωση) +@msg instruction budget προϋπολογισμός εντολών +@msg time budget χρονικός προϋπολογισμός +@msg memory budget (the selection is too large to hand over) προϋπολογισμός μνήμης (η επιλογή είναι πολύ μεγάλη για να παραδοθεί) +@msg output size ({what} is {len} bytes, limit {max}) μέγεθος εξόδου ({what}: {len} byte, όριο {max}) +@msg the plug-in's grant can't be removed from the plug-in store η άδεια του πρόσθετου δεν μπορεί να αφαιρεθεί από τον χώρο αποθήκευσης πρόσθετων @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it το δικαίωμα `{shown}` είναι δεσμευμένο για μεταγενέστερο API προσθέτων· αυτός ο κεντρικός υπολογιστής δεν το παραχωρεί @msg unknown permission `{shown}` άγνωστο δικαίωμα `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants το «{name}» ζητά τα δικαιώματα {asked}: πρέπει να τα εγκρίνει ένα άτομο στην εφαρμογή επιφάνειας εργασίας ή περάστε `grant` σε μια συνεδρία που ξεκίνησε με --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 24f5e0e39..2effb34a3 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -5998,6 +5998,11 @@ axis Y Axis Eje Y @msg `inputs` needs the permission `doc.read` `inputs` requiere el permiso `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) presupuesto de memoria (el objeto {_1} necesita {size} bytes de entrada, quedan {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) presupuesto de objetos (más de {MAX_OBJECTS} objetos de solo lectura) +@msg instruction budget presupuesto de instrucciones +@msg time budget presupuesto de tiempo +@msg memory budget (the selection is too large to hand over) presupuesto de memoria (la selección es demasiado grande para entregarla) +@msg output size ({what} is {len} bytes, limit {max}) tamaño de salida ({what} ocupa {len} bytes, límite {max}) +@msg the plug-in's grant can't be removed from the plug-in store el permiso del plugin no se puede quitar del almacén de plugins @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it el permiso `{shown}` está reservado para una API de plugins posterior; este host no lo concede @msg unknown permission `{shown}` permiso desconocido `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants “{name}” pide los permisos {asked}: una persona debe aprobarlos en la aplicación de escritorio, o pasa `grant` en una sesión iniciada con --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/fi.tsv b/crates/ui-egui/src/i18n/fi.tsv index 64b3f2b6f..6f7d04cb7 100644 --- a/crates/ui-egui/src/i18n/fi.tsv +++ b/crates/ui-egui/src/i18n/fi.tsv @@ -6086,6 +6086,11 @@ axis Y Axis Y-akseli @msg `inputs` needs the permission `doc.read` `inputs` edellyttää käyttöoikeutta `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) muistibudjetti (objekti {_1} tarvitsee {size} tavua syötettä, jäljellä {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) objektibudjetti (yli {MAX_OBJECTS} vain luku -objektia) +@msg instruction budget käskybudjetti +@msg time budget aikabudjetti +@msg memory budget (the selection is too large to hand over) muistibudjetti (valinta on liian suuri luovutettavaksi) +@msg output size ({what} is {len} bytes, limit {max}) tulosteen koko ({what}: {len} tavua, raja {max}) +@msg the plug-in's grant can't be removed from the plug-in store laajennuksen käyttöoikeutta ei voi poistaa laajennusvarastosta @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it käyttöoikeus `{shown}` on varattu myöhemmälle laajennus-API:lle; tämä isäntä ei myönnä sitä @msg unknown permission `{shown}` tuntematon käyttöoikeus `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants ”{name}” pyytää käyttöoikeuksia {asked}: ihmisen on hyväksyttävä ne työpöytäsovelluksessa, tai anna `grant` istunnossa, joka on käynnistetty valitsimella --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index dad99bcb4..f12ea2318 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -6052,6 +6052,11 @@ axis Y Axis Axe Y @msg `inputs` needs the permission `doc.read` `inputs` nécessite l’autorisation `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) budget mémoire (l’objet {_1} nécessite {size} octets d’entrée, il en reste {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) budget d’objets (plus de {MAX_OBJECTS} objets en lecture seule) +@msg instruction budget budget d’instructions +@msg time budget budget de temps +@msg memory budget (the selection is too large to hand over) budget mémoire (la sélection est trop grande pour être transmise) +@msg output size ({what} is {len} bytes, limit {max}) taille de sortie ({what} fait {len} octets, limite {max}) +@msg the plug-in's grant can't be removed from the plug-in store l’autorisation du plug-in ne peut pas être retirée du magasin de plug-ins @msg unknown permission `{shown}` autorisation inconnue `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants « {name} » demande les autorisations {asked} : une personne doit les approuver dans l’application de bureau, ou passez `grant` dans une session démarrée avec --allow-plugin-grants @msg `grant` and `allowHeavy` take effect only in a session started with --allow-plugin-grants: approve the plug-in in the desktop app `grant` et `allowHeavy` ne prennent effet que dans une session démarrée avec --allow-plugin-grants : approuvez le module externe dans l’application de bureau diff --git a/crates/ui-egui/src/i18n/hi.tsv b/crates/ui-egui/src/i18n/hi.tsv index 940858470..dfacf8974 100644 --- a/crates/ui-egui/src/i18n/hi.tsv +++ b/crates/ui-egui/src/i18n/hi.tsv @@ -5364,6 +5364,7 @@ antiAlias Sharp शार्प @msg `inputs` needs the permission `doc.read` `inputs` के लिए अनुमति `doc.read` आवश्यक है @msg memory budget (object {_1} needs {size} bytes of input, {left} left) मेमोरी बजट (ऑब्जेक्ट {_1} को इनपुट के {size} बाइट चाहिए, {left} शेष हैं) @msg object budget (more than {MAX_OBJECTS} read-only objects) ऑब्जेक्ट बजट ({MAX_OBJECTS} से अधिक केवल-पठन ऑब्जेक्ट) +@msg the plug-in's grant can't be removed from the plug-in store प्लग-इन की अनुमति प्लग-इन स्टोर से हटाई नहीं जा सकती @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it अनुमति `{shown}` बाद के प्लग-इन API के लिए आरक्षित है; यह होस्ट इसे नहीं देता @msg unknown permission `{shown}` अज्ञात अनुमति `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants “{name}” अनुमतियां {asked} मांगता है: इन्हें डेस्कटॉप ऐप में किसी व्यक्ति को स्वीकृत करना होगा, या --allow-plugin-grants से शुरू किए गए सत्र में `grant` दें diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 8f37efc8c..3b4fbd30b 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -6039,6 +6039,11 @@ axis Y Axis Y tengely @msg `inputs` needs the permission `doc.read` az `inputs` használatához a(z) `doc.read` engedély szükséges @msg memory budget (object {_1} needs {size} bytes of input, {left} left) memóriakeret (a(z) {_1} objektumnak {size} bájt bemenet kell, {left} maradt) @msg object budget (more than {MAX_OBJECTS} read-only objects) objektumkeret (több mint {MAX_OBJECTS} csak olvasható objektum) +@msg instruction budget utasításkeret +@msg time budget időkeret +@msg memory budget (the selection is too large to hand over) memóriakeret (a kijelölés túl nagy az átadáshoz) +@msg output size ({what} is {len} bytes, limit {max}) kimenet mérete ({what}: {len} bájt, korlát {max}) +@msg the plug-in's grant can't be removed from the plug-in store a bővítmény engedélye nem távolítható el a bővítménytárból @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it a(z) `{shown}` engedély egy későbbi bővítmény-API számára van fenntartva; ez a gazdaprogram nem adja meg @msg unknown permission `{shown}` ismeretlen engedély: `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants a(z) „{name}” a következő engedélyeket kéri: {asked}; egy személynek jóvá kell hagynia őket az asztali alkalmazásban, vagy add meg a `grant` értéket egy --allow-plugin-grants kapcsolóval indított munkamenetben diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 551fd25e4..32b41b249 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -5673,6 +5673,11 @@ axis Y Axis Asse Y @msg `inputs` needs the permission `doc.read` `inputs` richiede l’autorizzazione `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) budget di memoria (l’oggetto {_1} richiede {size} byte di input, ne restano {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) budget di oggetti (più di {MAX_OBJECTS} oggetti di sola lettura) +@msg instruction budget budget di istruzioni +@msg time budget budget di tempo +@msg memory budget (the selection is too large to hand over) budget di memoria (la selezione è troppo grande per essere passata) +@msg output size ({what} is {len} bytes, limit {max}) dimensione dell’output ({what} è di {len} byte, limite {max}) +@msg the plug-in's grant can't be removed from the plug-in store il permesso del plug-in non può essere rimosso dall’archivio dei plug-in @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it l’autorizzazione `{shown}` è riservata a un’API dei plug-in successiva; questo host non la concede @msg unknown permission `{shown}` autorizzazione sconosciuta `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants “{name}” chiede le autorizzazioni {asked}: una persona deve approvarle nell’app desktop, oppure passa `grant` in una sessione avviata con --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index 50a503e7f..61bf8c0d0 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -5738,6 +5738,11 @@ axis Y Axis Y 軸 @msg `inputs` needs the permission `doc.read` `inputs` には権限 `doc.read` が必要です @msg memory budget (object {_1} needs {size} bytes of input, {left} left) メモリ予算 (オブジェクト {_1} には {size} バイトの入力が必要ですが、残りは {left} です) @msg object budget (more than {MAX_OBJECTS} read-only objects) オブジェクト予算 ({MAX_OBJECTS} 個を超える読み取り専用オブジェクト) +@msg instruction budget 命令予算 +@msg time budget 時間予算 +@msg memory budget (the selection is too large to hand over) メモリ予算 (選択範囲が大きすぎて渡せません) +@msg output size ({what} is {len} bytes, limit {max}) 出力サイズ ({what} は {len} バイト、上限 {max}) +@msg the plug-in's grant can't be removed from the plug-in store プラグインの許可をプラグインストアから削除できません @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it 権限 `{shown}` は今後のプラグイン API 用に予約されています。このホストはこの権限を付与しません @msg unknown permission `{shown}` 不明な権限 `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants 「{name}」は権限 {asked} を求めています。デスクトップ アプリで人が承認するか、--allow-plugin-grants を付けて開始したセッションで `grant` を指定してください diff --git a/crates/ui-egui/src/i18n/ka.tsv b/crates/ui-egui/src/i18n/ka.tsv index a9aa3f2c3..e567dba4d 100644 --- a/crates/ui-egui/src/i18n/ka.tsv +++ b/crates/ui-egui/src/i18n/ka.tsv @@ -6007,6 +6007,11 @@ axis Y Axis Y ღერძი @msg `inputs` needs the permission `doc.read` `inputs`-ს სჭირდება ნებართვა `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) მეხსიერების ბიუჯეტი (ობიექტს {_1} სჭირდება შეყვანის {size} ბაიტი, დარჩენილია {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) ობიექტების ბიუჯეტი ({MAX_OBJECTS}-ზე მეტი მხოლოდ წასაკითხი ობიექტი) +@msg instruction budget ინსტრუქციების ბიუჯეტი +@msg time budget დროის ბიუჯეტი +@msg memory budget (the selection is too large to hand over) მეხსიერების ბიუჯეტი (მონიშნული ზედმეტად დიდია გადასაცემად) +@msg output size ({what} is {len} bytes, limit {max}) გამოტანის ზომა ({what}: {len} ბაიტი, ლიმიტი {max}) +@msg the plug-in's grant can't be removed from the plug-in store პლაგინის ნებართვის წაშლა პლაგინების საცავიდან შეუძლებელია @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it ნებართვა `{shown}` დაჯავშნილია პლაგინების მომავალი API-სთვის; ეს ჰოსტი მას არ გასცემს @msg unknown permission `{shown}` უცნობი ნებართვა `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants „{name}“ ითხოვს ნებართვებს {asked}: ისინი დესკტოპის აპში ადამიანმა უნდა დაამტკიცოს, ან გადაეცით `grant` --allow-plugin-grants-ით გაშვებულ სესიაში diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index e51fd6c3d..2dfcf3f97 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -5634,6 +5634,11 @@ axis Y Axis Y축 @msg `inputs` needs the permission `doc.read` `inputs`에는 `doc.read` 권한이 필요합니다 @msg memory budget (object {_1} needs {size} bytes of input, {left} left) 메모리 예산(개체 {_1}에 입력 {size}바이트가 필요하지만 {left}바이트 남음) @msg object budget (more than {MAX_OBJECTS} read-only objects) 개체 예산(읽기 전용 개체 {MAX_OBJECTS}개 초과) +@msg instruction budget 명령어 예산 +@msg time budget 시간 예산 +@msg memory budget (the selection is too large to hand over) 메모리 예산(선택 항목이 너무 커서 넘길 수 없음) +@msg output size ({what} is {len} bytes, limit {max}) 출력 크기({what}: {len}바이트, 제한 {max}) +@msg the plug-in's grant can't be removed from the plug-in store 플러그인 저장소에서 플러그인의 권한을 제거할 수 없습니다 @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it `{shown}` 권한은 이후 플러그인 API용으로 예약되어 있습니다. 이 호스트는 이 권한을 부여하지 않습니다 @msg unknown permission `{shown}` 알 수 없는 권한 `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants “{name}”은(는) {asked} 권한을 요청합니다. 데스크톱 앱에서 사람이 승인하거나 --allow-plugin-grants로 시작한 세션에서 `grant`를 전달하세요 diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index 0760b61ec..c13b992b8 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -5910,6 +5910,11 @@ axis Y Axis Oś Y @msg `inputs` needs the permission `doc.read` `inputs` wymaga uprawnienia `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) budżet pamięci (obiekt {_1} wymaga {size} bajtów danych wejściowych, pozostało {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) budżet obiektów (ponad {MAX_OBJECTS} obiektów tylko do odczytu) +@msg instruction budget budżet instrukcji +@msg time budget budżet czasu +@msg memory budget (the selection is too large to hand over) budżet pamięci (zaznaczenie jest zbyt duże, aby je przekazać) +@msg output size ({what} is {len} bytes, limit {max}) rozmiar wyjścia ({what} ma {len} bajtów, limit {max}) +@msg the plug-in's grant can't be removed from the plug-in store nie można usunąć uprawnienia wtyczki z magazynu wtyczek @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it uprawnienie `{shown}` jest zarezerwowane dla późniejszego API wtyczek; ten host go nie przyznaje @msg unknown permission `{shown}` nieznane uprawnienie `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants „{name}” prosi o uprawnienia {asked}: musi je zatwierdzić osoba w aplikacji desktopowej albo przekaż `grant` w sesji uruchomionej z --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index 1e37e7f55..041f58bb3 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -5971,6 +5971,11 @@ axis Y Axis Eixo Y @msg `inputs` needs the permission `doc.read` `inputs` exige a permissão `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) orçamento de memória (o objeto {_1} precisa de {size} bytes de entrada, restam {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) orçamento de objetos (mais de {MAX_OBJECTS} objetos somente leitura) +@msg instruction budget orçamento de instruções +@msg time budget orçamento de tempo +@msg memory budget (the selection is too large to hand over) orçamento de memória (a seleção é grande demais para ser entregue) +@msg output size ({what} is {len} bytes, limit {max}) tamanho da saída ({what} tem {len} bytes, limite {max}) +@msg the plug-in's grant can't be removed from the plug-in store a permissão do plug-in não pode ser removida do armazenamento de plug-ins @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it a permissão `{shown}` está reservada para uma API de plug-in futura; este host não a concede @msg unknown permission `{shown}` permissão desconhecida `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants “{name}” pede as permissões {asked}: uma pessoa precisa aprová-las no aplicativo de desktop, ou passe `grant` em uma sessão iniciada com --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index de1d31fd1..017f158c6 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -5667,6 +5667,11 @@ axis Y Axis Ось Y @msg `inputs` needs the permission `doc.read` для `inputs` нужно разрешение `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) бюджет памяти (объекту {_1} нужно {size} байт входных данных, осталось {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) бюджет объектов (более {MAX_OBJECTS} объектов только для чтения) +@msg instruction budget бюджет инструкций +@msg time budget бюджет времени +@msg memory budget (the selection is too large to hand over) бюджет памяти (выделение слишком велико для передачи) +@msg output size ({what} is {len} bytes, limit {max}) размер вывода ({what}: {len} байт, предел {max}) +@msg the plug-in's grant can't be removed from the plug-in store разрешение модуля нельзя удалить из хранилища модулей @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it разрешение `{shown}` зарезервировано для будущего API модулей; этот хост его не выдаёт @msg unknown permission `{shown}` неизвестное разрешение `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants «{name}» запрашивает разрешения {asked}: их должен одобрить человек в настольном приложении, либо передайте `grant` в сеансе, запущенном с --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index a3939998e..8c213d520 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -6079,6 +6079,7 @@ axis Y Axis Y-axel @msg `inputs` needs the permission `doc.read` `inputs` kräver behörigheten `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) minnesbudget (objekt {_1} behöver {size} byte indata, {left} återstår) @msg object budget (more than {MAX_OBJECTS} read-only objects) objektbudget (fler än {MAX_OBJECTS} skrivskyddade objekt) +@msg the plug-in's grant can't be removed from the plug-in store pluginets behörighet kan inte tas bort ur pluginlagret @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it behörigheten `{shown}` är reserverad för ett senare plugin-API; den här värden beviljar den inte @msg unknown permission `{shown}` okänd behörighet `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants ”{name}” begär behörigheterna {asked}: en person måste godkänna dem i skrivbordsappen, eller skicka `grant` i en session som startats med --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/tests.rs b/crates/ui-egui/src/i18n/tests.rs index 79cbd7a64..1b8110bdd 100644 --- a/crates/ui-egui/src/i18n/tests.rs +++ b/crates/ui-egui/src/i18n/tests.rs @@ -1878,7 +1878,7 @@ fn width(p: &Value, cmd: &str, key: &str) -> Result { } "##; let engine: Vec<_> = ERROR_HELPERS.iter().filter(|(c, _, _)| *c == "engine").map(|&(_, call, before)| (call, before)).collect(); - let found = source_messages(code, &engine); + let found = source_messages(code, &engine, &Default::default()); for want in [ "`{key}` must be a number", "the width can't be negative", @@ -1897,7 +1897,7 @@ fn width(p: &Value, cmd: &str, key: &str) -> Result { } let named = |m: &String| m.contains("not an error") || m.contains("not.an.error") || m.contains("not.a.reason"); assert!(!found.iter().any(named), "{found:#?}"); - let elsewhere = source_messages(code, &[]); + let elsewhere = source_messages(code, &[], &Default::default()); let in_variants = ["nested", "manifest", "nothing to clear", "panel is locked"]; assert!(elsewhere.len() == 4 && elsewhere.iter().all(|m| in_variants.iter().any(|w| m.contains(w))), "{elsewhere:#?}"); // A message read this way matches its row: `{key}` keeps its name. @@ -1905,6 +1905,76 @@ fn width(p: &Value, cmd: &str, key: &str) -> Result { assert_eq!(c.message("`width` must be a number").map(|m| m.1), Some(vec![("key", "width")])); } +/// The scan reads a message that an error or a status takes from a `&str` constant, by its name or +/// by its path, with `.into()`, `.to_string()` or nothing after it, and the constant declared in +/// another file. It does not read a constant that no error takes, a call of a name that a constant +/// also has, or a constant in a comment. +#[test] +fn message_scan_reads_messages_held_in_constants() { + let declared = r#" +pub(crate) const TOO_LARGE: &str = "the selection is too large to hand over"; +pub const SLOW: &'static str = "time budget"; +const UNUSED: &str = "not an error: a constant no error takes"; +const fn NOT_A_STR() -> u32 { 0 } +// const COMMENTED: &str = "not an error: a constant in a comment"; +"#; + let code = r#" +fn run() -> Result<()> { + let _ = Error::Limit(crate::runtime::TOO_LARGE.into()); + let _ = Err(Error::Limit(SLOW.to_string())); + let _ = Err(COMMENTED); + let _ = Err(SLOW(3)); + Ok(()) +} +"#; + let mut consts = std::collections::BTreeMap::new(); + for (name, value) in str_consts(declared) { + consts.entry(name).or_insert_with(Vec::new).push(value); + } + assert_eq!(consts.keys().collect::>(), ["SLOW", "TOO_LARGE", "UNUSED"]); + let found: std::collections::BTreeSet = source_messages(code, &[], &consts).into_iter().collect(); + assert_eq!(found.iter().collect::>(), ["the selection is too large to hand over", "time budget"]); + assert!(source_messages(code, &[], &Default::default()).is_empty()); +} + +/// The limits a plug-in run can exceed, and the error of a removal that leaves the plug-in's grant +/// in the plug-in store, are translated in every language that translates every message, as the +/// status bar shows them. +#[test] +fn plugin_limit_errors_are_translated() { + use vectorcraft_plugins::Error; + let scanned = message_literals(); + let grant = "the plug-in's grant can't be removed from the plug-in store"; + let templates = [ + "instruction budget", + "time budget", + "memory budget (the selection is too large to hand over)", + "output size ({what} is {len} bytes, limit {max})", + grant, + ]; + for template in templates { + assert!(scanned.contains(template), "{template}"); + } + let limits = [ + "instruction budget", + "time budget", + "memory budget (the selection is too large to hand over)", + "output size (the result is 9000 bytes, limit 4096)", + ]; + for code in COMPLETE_MESSAGES { + let lang = Lang::from_code(code).expect("registered"); + for limit in limits { + let shown = message(lang, limit); + assert_ne!(shown, limit, "{code}"); + let whole = message(lang, &Error::Limit(limit.into()).to_string()); + assert!(whole.contains(&shown) && !whole.contains("exceeded"), "{code}: {whole}"); + } + let shown = message(lang, limits[3]); + assert!(shown.contains("9000") && shown.contains("4096") && !shown.contains("output size"), "{code}: {shown}"); + assert_ne!(message(lang, grant), grant, "{code}"); + } +} + /// The warnings of an Image Trace with keepColors, which the status bar shows and the scan above /// doesn't read, are translated in each language of [`COMPLETE_MESSAGES`], with the colors kept. #[test] @@ -2545,6 +2615,7 @@ const NOT_MESSAGES: &[&str] = &["quit", "cancelled"]; pub fn message_literals() -> std::collections::BTreeSet { let crates = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join(".."); let mut out = std::collections::BTreeSet::new(); + let mut files = vec![]; let mut stack: Vec<_> = MESSAGE_CRATES.iter().map(|c| crates.join(c).join("src")).collect(); while let Some(d) = stack.pop() { for entry in std::fs::read_dir(&d).into_iter().flatten().flatten() { @@ -2558,22 +2629,61 @@ pub fn message_literals() -> std::collections::BTreeSet { // Control replies are English protocol data, never status-bar messages // (see i18n's module contract). Engine messages are scanned in their own crates. let text = std::fs::read_to_string(&path).unwrap_or_default(); - let helpers: Vec<_> = - ERROR_HELPERS.iter().filter(|(c, _, _)| path.starts_with(crates.join(c))).map(|&(_, call, before)| (call, before)).collect(); - out.extend(source_messages(without_test_module(&text), &helpers)); + files.push((path, text)); } } } + let mut consts = std::collections::BTreeMap::new(); + for (_, text) in &files { + for (name, value) in str_consts(without_test_module(text)) { + consts.entry(name).or_insert_with(Vec::new).push(value); + } + } + for (path, text) in &files { + let helpers: Vec<_> = + ERROR_HELPERS.iter().filter(|(c, _, _)| path.starts_with(crates.join(c))).map(|&(_, call, before)| (call, before)).collect(); + out.extend(source_messages(without_test_module(text), &helpers, &consts)); + } out } +/// The `&str` constants `code` declares outside its comments (`const NAME: &str = "…";`), with +/// their text, escapes resolved. +fn str_consts(code: &str) -> Vec<(String, String)> { + let code = &without_comments(code); + code.match_indices("const ") + .filter(|&(at, _)| !code[..at].ends_with(|c: char| c.is_alphanumeric() || c == '_')) + .filter_map(|(at, m)| { + let rest = &code[at + m.len()..]; + let (name, rest) = rest.split_at(rest.find(|c: char| !c.is_ascii_alphanumeric() && c != '_')?); + let rest = rest.trim_start().strip_prefix(':')?.trim_start(); + let rest = rest.strip_prefix("&'static str").or_else(|| rest.strip_prefix("&str"))?.trim_start(); + let value = string_literal(rest.strip_prefix('=')?.trim_start().strip_prefix('"')?)?; + Some((name.to_string(), value)) + }) + .collect() +} + +/// The text of the constant that `rest` starts with, by name or by path (`TIME_BUDGET`, +/// `crate::runtime::SELECTION_TOO_LARGE.into()`), when `consts` holds it: every text, when crates +/// declare constants of that name with different texts. +fn named_const<'a>(rest: &str, consts: &'a std::collections::BTreeMap>) -> &'a [String] { + let path = &rest[..rest.find(|c: char| !c.is_ascii_alphanumeric() && c != '_' && c != ':').unwrap_or(rest.len())]; + let after = &rest[path.len()..]; + let used = [")", ",", ".into()", ".to_string()", ".to_owned()"].iter().any(|end| after.starts_with(end)); + let name = path.rsplit("::").next().unwrap_or(""); + let upper = name.starts_with(|c: char| c.is_ascii_uppercase()) && name.chars().all(|c| c.is_ascii_uppercase() || c.is_ascii_digit() || c == '_'); + if used && upper { consts.get(name).map_or(&[], Vec::as_slice) } else { &[] } +} + /// The message literals in `code` outside its comments, as catalog templates (see /// [`message_literals`]): the literal after each of [`MESSAGE_MARKERS`], the message argument of an /// error enum's variant (the first, as in `PsError::Limit(…)` and `Error::Manifest(…)`, or the one /// [`LATER_MESSAGE_VARIANTS`] gives; not [`NAME_VARIANTS`]), /// and the message argument of each call in `helpers` (a call and the number of arguments before -/// its message), a literal or a `format!` string. -fn source_messages(code: &str, helpers: &[(&str, usize)]) -> Vec { +/// its message), a literal, a `format!` string or the name of one of `consts` (see +/// [`str_consts`]). +fn source_messages(code: &str, helpers: &[(&str, usize)], consts: &std::collections::BTreeMap>) -> Vec { let code = &without_comments(code); let after_markers = MESSAGE_MARKERS.iter().flat_map(|marker| code.match_indices(marker).map(|(at, _)| &code[at + marker.len()..])); let in_variants = code.match_indices("Error::").filter_map(|(at, m)| { @@ -2592,10 +2702,15 @@ fn source_messages(code: &str, helpers: &[(&str, usize)]) -> Vec { for rest in after_markers.chain(in_variants).chain(in_helpers) { let rest = rest.trim_start(); let rest = rest.strip_prefix("format!(").map_or(rest, str::trim_start); - let Some(lit) = rest.strip_prefix('"').and_then(string_literal) else { continue }; - let has_word = lit.as_bytes().windows(3).any(|w| w.iter().all(u8::is_ascii_lowercase)); - if has_word && !NOT_MESSAGES.contains(&lit.as_str()) { - out.push(as_template(&lit)); + let lits = match rest.strip_prefix('"') { + Some(quoted) => string_literal(quoted).into_iter().collect(), + None => named_const(rest, consts).to_vec(), + }; + for lit in lits { + let has_word = lit.as_bytes().windows(3).any(|w| w.iter().all(u8::is_ascii_lowercase)); + if has_word && !NOT_MESSAGES.contains(&lit.as_str()) { + out.push(as_template(&lit)); + } } } out diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 17f25cf77..a601ee6c5 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -6012,6 +6012,11 @@ axis Y Axis Y ekseni @msg `inputs` needs the permission `doc.read` `inputs` için `doc.read` izni gerekir @msg memory budget (object {_1} needs {size} bytes of input, {left} left) bellek bütçesi (nesne {_1} için {size} bayt girdi gerekiyor, {left} kaldı) @msg object budget (more than {MAX_OBJECTS} read-only objects) nesne bütçesi ({MAX_OBJECTS} adetten fazla salt okunur nesne) +@msg instruction budget talimat bütçesi +@msg time budget zaman bütçesi +@msg memory budget (the selection is too large to hand over) bellek bütçesi (seçim aktarılamayacak kadar büyük) +@msg output size ({what} is {len} bytes, limit {max}) çıktı boyutu ({what}: {len} bayt, sınır {max}) +@msg the plug-in's grant can't be removed from the plug-in store eklentinin izni eklenti deposundan kaldırılamıyor @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it `{shown}` izni sonraki bir eklenti API’si için ayrılmıştır; bu ana bilgisayar bu izni vermez @msg unknown permission `{shown}` bilinmeyen izin `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants “{name}” {asked} izinlerini istiyor: masaüstü uygulamasında bir kişinin onaylaması gerekir veya --allow-plugin-grants ile başlatılan bir oturumda `grant` geçirin diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index f9412ed97..8ee30242e 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -5653,6 +5653,11 @@ axis Y Axis Вісь Y @msg `inputs` needs the permission `doc.read` для `inputs` потрібен дозвіл `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) бюджет пам’яті (об’єкту {_1} потрібно {size} байтів вхідних даних, залишилося {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) бюджет об’єктів (понад {MAX_OBJECTS} об’єктів лише для читання) +@msg instruction budget бюджет інструкцій +@msg time budget бюджет часу +@msg memory budget (the selection is too large to hand over) бюджет пам’яті (виділення завелике для передавання) +@msg output size ({what} is {len} bytes, limit {max}) розмір виводу ({what}: {len} байтів, межа {max}) +@msg the plug-in's grant can't be removed from the plug-in store дозвіл модуля не вдається вилучити зі сховища модулів @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it дозвіл `{shown}` зарезервовано для пізнішого API модулів; цей хост його не надає @msg unknown permission `{shown}` невідомий дозвіл `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants «{name}» запитує дозволи {asked}: їх має схвалити людина в настільному застосунку, або передайте `grant` у сеансі, запущеному з --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index e26e81852..a26198360 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -5654,6 +5654,11 @@ axis Y Axis Trục Y @msg `inputs` needs the permission `doc.read` `inputs` cần quyền `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) ngân sách bộ nhớ (đối tượng {_1} cần {size} byte đầu vào, còn lại {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) ngân sách đối tượng (hơn {MAX_OBJECTS} đối tượng chỉ đọc) +@msg instruction budget ngân sách lệnh +@msg time budget ngân sách thời gian +@msg memory budget (the selection is too large to hand over) ngân sách bộ nhớ (vùng chọn quá lớn để chuyển giao) +@msg output size ({what} is {len} bytes, limit {max}) kích thước đầu ra ({what} là {len} byte, giới hạn {max}) +@msg the plug-in's grant can't be removed from the plug-in store không thể xóa quyền của plug-in khỏi kho plug-in @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it quyền `{shown}` được dành cho một API plug-in sau này; máy chủ này không cấp quyền đó @msg unknown permission `{shown}` quyền không xác định `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants “{name}” yêu cầu các quyền {asked}: cần một người phê duyệt trong ứng dụng máy tính, hoặc truyền `grant` trong phiên khởi động bằng --allow-plugin-grants diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 855001a82..e34d048d4 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -5894,6 +5894,11 @@ axis Y Axis Y 轴 @msg `inputs` needs the permission `doc.read` `inputs` 需要权限 `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) 内存预算(对象 {_1} 需要 {size} 字节的输入,剩余 {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) 对象预算(超过 {MAX_OBJECTS} 个只读对象) +@msg instruction budget 指令预算 +@msg time budget 时间预算 +@msg memory budget (the selection is too large to hand over) 内存预算(所选内容太大,无法传递) +@msg output size ({what} is {len} bytes, limit {max}) 输出大小({what} 为 {len} 字节,上限 {max}) +@msg the plug-in's grant can't be removed from the plug-in store 无法从增效工具存储中移除该增效工具的授权 @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it 权限 `{shown}` 保留给以后的增效工具 API;此主机不授予该权限 @msg unknown permission `{shown}` 未知权限 `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants “{name}”需要权限 {asked}:需要有人在桌面应用中批准,或在以 --allow-plugin-grants 启动的会话中传入 `grant` diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 2002c06ef..5997dfb37 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -5691,6 +5691,11 @@ axis Y Axis Y 軸 @msg `inputs` needs the permission `doc.read` `inputs` 需要權限 `doc.read` @msg memory budget (object {_1} needs {size} bytes of input, {left} left) 記憶體預算(物件 {_1} 需要 {size} 位元組的輸入,剩餘 {left}) @msg object budget (more than {MAX_OBJECTS} read-only objects) 物件預算(超過 {MAX_OBJECTS} 個唯讀物件) +@msg instruction budget 指令預算 +@msg time budget 時間預算 +@msg memory budget (the selection is too large to hand over) 記憶體預算(所選內容太大,無法傳遞) +@msg output size ({what} is {len} bytes, limit {max}) 輸出大小({what} 為 {len} 位元組,上限 {max}) +@msg the plug-in's grant can't be removed from the plug-in store 無法從增效模組存放區移除該增效模組的授權 @msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it 權限 `{shown}` 保留給日後的增效模組 API;此主機不授予該權限 @msg unknown permission `{shown}` 未知權限 `{shown}` @msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants 「{name}」需要權限 {asked}:需要有人在桌面應用程式中核准,或在以 --allow-plugin-grants 啟動的工作階段中傳入 `grant` diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 21081966b..5dcc013da 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -785,6 +785,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - Window › Help Bar shows or hides the tool-help strip at the bottom of the window apart from the status bar (`window.helpBar`). Each setting is kept with the UI preferences and in saved workspaces, and Presentation Mode hides both bars. Layouts saved before the setting existed show the Help Bar where they show the status bar (`help_bar_toggle_is_independent_and_saved_in_workspaces`, `help_bar_and_status_bar_render_independently`, `legacy_help_bar_visibility_follows_each_layouts_status_bar`, `a_help_bar_setting_the_file_lacks_is_saved`). - Czech render-site labels: desktop/web file filters, diagnostics, suggested preset names and contributor tooltips/plurals now use catalog lookups; gradients have Czech adjective agreement and printer marks have a separate context (PDF/Print and Summary). Search, Home, toolbar/panel tooltips and Preferences already look up their labels. Every complete catalog has rows for these labels and for the Roman and Japanese printer mark styles. Evidence: `i18n::tests::czech_render_site_follow_up`, `i18n::tests::complete_catalogs_translate_render_site_labels`, `dialogs::tests_modal::printer_mark_labels_are_distinct_from_language_names`; see [localization-parity.md](localization-parity.md). - The History panel, Edit › Undo and Edit › Redo translate the names of the steps that apply or redefine a character or paragraph style and of the step that redefines a graphic style: each such step keeps its template (`Apply {name}`, `Redefine {name}`, `Redefine Graphic Style “{name}”`) and the style's name, every complete catalog has a row for each template, and the panel and the menu show the style's name as the document holds it, except the Normal styles' names, which they show in the interface language (`steps_named_after_a_style_list_the_template_around_the_name`, `undo_and_redo_name_a_style_step_around_the_style_name`). + - The status bar translates the limits a plug-in run can exceed (its instruction, time and memory budgets and its output size) and the error of a plug-in removal that leaves the plug-in's grant in the plug-in store, in every language that translates every message. The untranslated-strings report also lists messages that an error or a status takes from a `&str` constant (`plugin_limit_errors_are_translated`, `message_scan_reads_messages_held_in_constants`). - Localised UI: menus (in-window and native), panels, dialogs, toolbar and Preferences read from per-language catalogs (`crates/ui-egui/src/i18n`, see `docs/development.md`); Traditional Chinese (Taiwan), Simplified Chinese (mainland), Japanese, Korean, Vietnamese, German, Spanish, French, Italian, Polish, Brazilian Portuguese, Russian, Ukrainian, Georgian and Catalan ship complete, and Czech covers every menu label (and more), with system-locale detection on macOS, Windows, Linux and the web (the browser's languages, or `?lang=`), a Language preference and, on macOS, a VectorCraft ▸ Language menu. Names are never translated (fonts and their styles, layers, artboards, saved presets, user libraries, custom workspaces, recent files, plug-ins). The counts that Package's status and question, the folder search of Missing Fonts and Find Linked Files, the modified and missing linked file prompts and the CSS Properties panel's notes show use the interface language's plural forms instead of a fixed "(s)" form. Evidence: `the_missing_links_note_uses_each_count_form` in `crates/ui-egui/src/dialogs/tests_package.rs`, `the_modified_links_question_uses_each_count_form` in `crates/ui-egui/src/dialogs/missing_links.rs`, `search_counts_use_each_count_form` in `crates/ui-egui/src/dialogs/missing_fonts/tests.rs` and `the_unnamed_objects_note_uses_each_count_form` in `crates/ui-egui/src/panels/tests_css_properties.rs`. The status bar's messages for relinked, replaced, updated and embedded images, broken links, linked files that can't be read or changed on disk, images that can't be decoded, added and unavailable fonts, copied CSS, downloads and exports with their notes name one item in the singular and more in the plural, in English and in each language's plural forms (`counted_status_messages_take_the_plural_form` in `crates/ui-egui/src/i18n/tests.rs`).