From 5c9bf373bb7cdccd309e0f990c715fbc782c79ce Mon Sep 17 00:00:00 2001 From: Hengfei Yang Date: Wed, 4 Nov 2026 15:23:17 +0000 Subject: [PATCH] fix(fleet): return fleet delete counts and correct three console behaviours (#16394) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- scripts/translations/.translation_state.json | 42 ++++++++++++++-- src/api/management/src/request/fleet/mod.rs | 37 ++++++++++---- src/api/management/src/request/folders.rs | 4 +- src/db/src/folders.rs | 7 +++ web/src/components/fleet/FleetFleets.spec.ts | 1 + .../fleet/FleetRemoveDialog.spec.ts | 3 ++ web/src/locales/languages/ar-SA.json | 42 ++++++++++++++-- web/src/locales/languages/de-DE.json | 42 ++++++++++++++-- web/src/locales/languages/en-US.json | 5 +- web/src/locales/languages/es-ES.json | 42 ++++++++++++++-- web/src/locales/languages/fr-FR.json | 42 ++++++++++++++-- web/src/locales/languages/it-IT.json | 42 ++++++++++++++-- web/src/locales/languages/ja-JP.json | 42 ++++++++++++++-- web/src/locales/languages/ko-KR.json | 42 ++++++++++++++-- web/src/locales/languages/nl-NL.json | 42 ++++++++++++++-- web/src/locales/languages/pl-PL.json | 42 ++++++++++++++-- web/src/locales/languages/pt-PT.json | 42 ++++++++++++++-- web/src/locales/languages/ru-RU.json | 42 ++++++++++++++-- web/src/locales/languages/th-TH.json | 42 ++++++++++++++-- web/src/locales/languages/tr-TR.json | 42 ++++++++++++++-- web/src/locales/languages/vi-VN.json | 42 ++++++++++++++-- web/src/locales/languages/zh-CN.json | 42 ++++++++++++++-- web/src/locales/languages/zh-TW.json | 42 ++++++++++++++-- web/src/services/fleet.mock.ts | 9 +++- web/src/views/FleetConfigEditor.spec.ts | 16 ++++++ web/src/views/FleetConfigEditor.vue | 49 +++++++++++-------- 26 files changed, 726 insertions(+), 119 deletions(-) diff --git a/scripts/translations/.translation_state.json b/scripts/translations/.translation_state.json index 96bd10958a..5d3ee9348c 100644 --- a/scripts/translations/.translation_state.json +++ b/scripts/translations/.translation_state.json @@ -252,6 +252,22 @@ "feature_traces": "998741a58ed2b411", "feature_vrl_functions": "4484dd94e9355480", "feature_workload_management": "8004f04c30d8bddc", + "features": "5697d03daef4de9c", + "features_all_unlocked": "0791a3840eb6061a", + "features_filter_all": "a52ace420f2175d0", + "features_filter_free": "f411a1fb62758b4c", + "features_filter_new": "18fdd549b2ed367a", + "features_free_heading": "5892004a2a606ee5", + "features_group_heading": "98bb11ae86a0c557", + "features_missing": "694943b3db420a2e", + "features_new": "d9fe8aa562864fe0", + "features_no_match": "c7655586749bb9b3", + "features_none": "6b474f2c0cba33e7", + "features_paid_ratio": "3257b4364ee32149", + "features_request_access": "22d6edf4b21d5e25", + "features_search": "55e327604647ce88", + "features_summary": "5d2957d8f8c9d8e7", + "features_unlocked": "531c7b28abf27600", "foreverNoLimits": "c4e4f35814b1022b", "fullyManaged": "49964f86a467ca7b", "gbPerDay": "dd9d1b63afeb0945", @@ -13060,6 +13076,19 @@ "tabLabel": "cb702378f31507ef", "title": "2a932f90172e99ea" }, + "featureLock": { + "bannerMessage": "2ad54d7dcf939937", + "bannerMessageGeneric": "9e4736ff1b60331d", + "contactSales": "604abea32b499a4c", + "description": "052f7504abd2c39a", + "headerLocked": "ce0f1697c8a3a6d5", + "routeTitle": "694943b3db420a2e", + "thisFeature": "2598604c06f0d223", + "title": "84027eb92891f1fd", + "toastMessage": "b17241a153486b9c", + "toastMessageGeneric": "4cf1f345d3caeb96", + "toastTitle": "feff10da75dad3ed" + }, "fleet": { "addCollector": "6d30a69cb01ed55a", "audit": { @@ -13191,7 +13220,7 @@ "remove": "c3812fc4acb861d5", "removeManyTitle": "dd8570212a038ad5", "removeMessage": "6c56329591483d78", - "removeOnlineMessage": "348378f9ab3956ea", + "removeOnlineMessage": "03752b97220cd6d8", "removeTitle": "01c1f0250884f593", "removedCount": "1f78b62d9f67b101", "rename": "3064d79a295cefe4", @@ -13200,6 +13229,7 @@ "restart": "6b983a81e5e8099e", "restartManyTitle": "b48d3498ba6feded", "restartMessage": "22ee1481ad969aff", + "restartOffline": "35842abc83dff75b", "restartQueued": "43da4197b31c94b2", "restartUnsupported": "322b4fd3d40b0ff7", "search": "773656193742d0b1", @@ -13315,6 +13345,7 @@ "publishBlocked": "d701e0b0d78ce738", "publishBlockedChip": "e0178dee5d72174d", "publishMessage": "0a411b50cf827314", + "publishUnchanged": "42d61ebf81d065f7", "publishVersion": "34c4b8bfed5ff137", "publishedToast": "4506fdd4b0e29987", "publishedWithWarnings": "6e1f061e4bcf1e88", @@ -13381,7 +13412,7 @@ "fleets": { "added": "0f3c3507a674bbc9", "allRollouts": "9cf13bc47185ccf7", - "atDesired": "c0e1d4dc91f6a3ff", + "atDesired": "2a2a3dcca6ef4355", "changeVersion": "4c236daafb445f86", "createFailed": "1e6d402d3870abbc", "delete": "ec99caf3122b6cb6", @@ -13535,7 +13566,7 @@ "confirmFixForward": "6e986df0401cda4a", "confirmResume": "323c118fa4613787", "confirmRollback": "ad34d76a7f53f6b5", - "confirmRollbackNoStable": "76cba5181ffc44a2", + "confirmRollbackNoStable": "5b00aa2620aa662d", "confirmSkip": "fbf2627372d3e0cc", "confirmed": "fe00b67b6dd1143f", "emptyFleet": "40e87c8e8e200c76", @@ -13596,6 +13627,7 @@ "phaseStopped": "1a4f630ac1b69fd0", "phaseTimedOut": "9718cc761cfd5810", "phaseTimeoutNote": "f11dc4d3138e81ac", + "phaseTimeoutNoteSeconds": "fafc2b0d6a049798", "phaseVerifying": "a7d4a9f301edaa61", "phases": "b4b0b75a774761b3", "pickConfig": "90ea303d63b6e1b9", @@ -13662,8 +13694,8 @@ "noAccess": "cb92165578c84ffb", "offlineHeartbeats": "b82c0b4fc3ceead6", "offlineHeartbeatsHelp": "91687a5a34666ebf", - "offlineRatio": "ab13785c48fe3a97", - "offlineRatioHelp": "8fa2bcd13b66f2f3", + "offlineRatio": "98affbf40cf01c0c", + "offlineRatioHelp": "fcf7765ecca25ef0", "outOfRange": "f9a9c12c180ebfe6", "phaseTimeout": "47d919e06d87345e", "phaseTimeoutHelp": "019f8feb0a24eaa2", diff --git a/src/api/management/src/request/fleet/mod.rs b/src/api/management/src/request/fleet/mod.rs index 874776b79d..90c0bda8cf 100644 --- a/src/api/management/src/request/fleet/mod.rs +++ b/src/api/management/src/request/fleet/mod.rs @@ -590,7 +590,7 @@ pub async fn rename_fleet( (status = 204, description = "Deleted"), (status = 403, description = "Forbidden", content_type = "application/json", body = Object), (status = 404, description = "Not found", content_type = "application/json", body = Object), - (status = 409, description = "Still referenced, the default fleet, or changing", content_type = "application/json", body = Object), + (status = 409, description = "Still referenced, with the counts in `references`; the default fleet; or changing", content_type = "application/json", body = Object), ), )] pub async fn delete_fleet( @@ -2109,6 +2109,7 @@ fn folder_response(e: db::folders::FolderError) -> Response { FolderError::DeleteFleet(message) | FolderError::FleetChanged(message) => { MetaHttpResponse::conflict(message) } + FolderError::FleetInUse(message, references) => in_use_response(message, &references), FolderError::PermittedFoldersMissingUser | FolderError::PermittedFoldersValidator(_) => { MetaHttpResponse::forbidden("Forbidden") } @@ -2119,6 +2120,16 @@ fn folder_response(e: db::folders::FolderError) -> Response { } } +#[cfg(feature = "enterprise")] +fn in_use_response(message: String, references: &config::meta::fleet::References) -> Response { + let body = serde_json::json!({ + "code": StatusCode::CONFLICT.as_u16(), + "message": message, + "references": references, + }); + (StatusCode::CONFLICT, axum::Json(body)).into_response() +} + /// The `sea-orm` text carries SQL fragments, so a server fault is logged, not returned. #[cfg(feature = "enterprise")] fn to_response(e: anyhow::Error) -> Response { @@ -2133,14 +2144,7 @@ fn to_response(e: anyhow::Error) -> Response { }; (StatusCode::UNPROCESSABLE_ENTITY, axum::Json(body)).into_response() } - Some(FleetError::ConfigInUse(_, references)) => { - let body = serde_json::json!({ - "code": StatusCode::CONFLICT.as_u16(), - "message": e.to_string(), - "references": references, - }); - (StatusCode::CONFLICT, axum::Json(body)).into_response() - } + Some(FleetError::ConfigInUse(_, references)) => in_use_response(e.to_string(), references), Some(err) => MetaHttpResponse::error(err.status_code(), e.to_string()).into_response(), None => { log::error!("[fleet] {e}"); @@ -2369,6 +2373,21 @@ mod tests { let res = to_response(FleetError::ConfigInUse("edge".into(), references).into()); assert_eq!(res.status(), StatusCode::CONFLICT); assert!(body_text(res).await.contains(r#""fleets":2"#)); + let references = config::meta::fleet::References { + collectors: 2, + tokens: 1, + ..Default::default() + }; + let res = folder_response(db::folders::FolderError::FleetInUse( + "fleet in use".to_string(), + references, + )); + assert_eq!(res.status(), StatusCode::CONFLICT); + let text = body_text(res).await; + assert!( + text.contains(r#""collectors":2"#) && text.contains(r#""tokens":1"#), + "{text}" + ); let other = to_response(anyhow::anyhow!("SELECT secret FROM x")); assert_eq!(other.status(), StatusCode::INTERNAL_SERVER_ERROR); assert!(!body_text(other).await.contains("SELECT secret")); diff --git a/src/api/management/src/request/folders.rs b/src/api/management/src/request/folders.rs index 2bc213b2c8..a2bd0478ef 100644 --- a/src/api/management/src/request/folders.rs +++ b/src/api/management/src/request/folders.rs @@ -58,7 +58,9 @@ fn folder_error_response(value: FolderError) -> Response { FolderError::DeleteWithPrompts => MetaHttpResponse::bad_request( "Folder contains prompts, please move/delete prompts from folder", ), - FolderError::DeleteFleet(message) => MetaHttpResponse::bad_request(message), + FolderError::DeleteFleet(message) | FolderError::FleetInUse(message, _) => { + MetaHttpResponse::bad_request(message) + } FolderError::FleetChanged(message) => MetaHttpResponse::conflict(message), FolderError::NotFound => MetaHttpResponse::not_found("Folder not found"), FolderError::PermittedFoldersMissingUser => MetaHttpResponse::forbidden(""), diff --git a/src/db/src/folders.rs b/src/db/src/folders.rs index e078f5f011..49697428b0 100644 --- a/src/db/src/folders.rs +++ b/src/db/src/folders.rs @@ -88,6 +88,10 @@ pub enum FolderError { #[error("{0}")] DeleteFleet(String), + /// A fleet holds collectors or live tokens, which the refusal counts. + #[error("{0}")] + FleetInUse(String, config::meta::fleet::References), + /// A fleet's revisions kept changing while it was being deleted. #[error("{0}")] FleetChanged(String), @@ -490,6 +494,9 @@ async fn delete_fleet(org_id: &str, folder_id: &str) -> Result<(), FolderError> Err(match e.downcast_ref::() { Some(FleetError::FleetNotFound(_)) => FolderError::NotFound, Some(FleetError::Invalid(message)) => FolderError::DeleteFleet(message.clone()), + Some(FleetError::FleetInUse(_, references)) => { + FolderError::FleetInUse(e.to_string(), references.clone()) + } Some(FleetError::RolloutState { .. }) => { FolderError::FleetChanged(format!("fleet {folder_id} is changing; retry")) } diff --git a/web/src/components/fleet/FleetFleets.spec.ts b/web/src/components/fleet/FleetFleets.spec.ts index a907df4aa3..e616631471 100644 --- a/web/src/components/fleet/FleetFleets.spec.ts +++ b/web/src/components/fleet/FleetFleets.spec.ts @@ -176,6 +176,7 @@ describe("FleetFleets", () => { expect(btn(wrapper, "desired").text()).toBe("edge-config v3"); expect(btn(wrapper, "stable").text()).toBe("edge-config v2"); expect(btn(wrapper, "members").text()).toBe("1 of 2 online"); + expect(wrapper.text()).toContain("1 of 2 assigned the desired version"); expect(btn(wrapper, "rollout-progress").text()).toContain("28 of 40 running the new version"); }); diff --git a/web/src/components/fleet/FleetRemoveDialog.spec.ts b/web/src/components/fleet/FleetRemoveDialog.spec.ts index b4e9bd4a5d..3515f83b04 100644 --- a/web/src/components/fleet/FleetRemoveDialog.spec.ts +++ b/web/src/components/fleet/FleetRemoveDialog.spec.ts @@ -67,6 +67,9 @@ describe("FleetRemoveDialog", () => { expect(w.find('[data-test="fleet-remove-dialog-message"]').text()).toContain( "uninstall it on its host first", ); + expect(w.find('[data-test="fleet-remove-dialog-message"]').text()).toContain( + "unless its enrollment token is used up", + ); const cmd = w.findComponent({ name: "FleetUninstallCommand" }); expect(cmd.props("platform")).toBe("macos"); expect(cmd.props("showPlatforms")).toBe(true); diff --git a/web/src/locales/languages/ar-SA.json b/web/src/locales/languages/ar-SA.json index fb6649bfb4..3f84c5c81e 100644 --- a/web/src/locales/languages/ar-SA.json +++ b/web/src/locales/languages/ar-SA.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "غير مشمول في ترخيصك", + "title": "لا يتضمن ترخيصك {feature}", + "description": "يمكن لمسؤول النظام إضافته عبر تحديث الترخيص، أو التواصل مع المبيعات للحصول على ترخيص يتضمنه.", + "thisFeature": "هذه الميزة", + "contactSales": "تواصل مع المبيعات", + "toastTitle": "غير مشمول في ترخيصك", + "toastMessage": "لا يتضمن ترخيصك: {features}. اطلب من مسؤول النظام تحديث الترخيص.", + "toastMessageGeneric": "لا يتضمن ترخيصك هذه الميزة. اطلب من مسؤول النظام تحديث الترخيص.", + "bannerMessage": "هذه الميزة مقفلة. تتطلب ميزة {feature} ضمن ترخيصك.", + "bannerMessageGeneric": "تحتاج هذه الصفحة إلى ميزة غير مشمولة في ترخيصك.", + "headerLocked": "مقفل: يتطلب {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "لا يوجد سجل بعد", @@ -3407,6 +3420,22 @@ "contact_name": "اسم الاتصال", "contact_email": "بريد إلكتروني للتواصل", "environment_type": "نوع البيئة", + "features": "الميزات", + "features_all_unlocked": "يتيح ترخيصك جميع الميزات.", + "features_summary": "يتيح ترخيصك {ratio}. تُضمّن {free} ميزة مجانية دائمًا. | يتيح ترخيصك {ratio}. تُضمّن {free} ميزات مجانية دائمًا.", + "features_paid_ratio": "{unlocked} من {paid} ميزة مدفوعة | {unlocked} من {paid} ميزات مدفوعة", + "features_unlocked": "متاح", + "features_missing": "غير مشمول في ترخيصك", + "features_request_access": "طلب الوصول", + "features_search": "ابحث في {count} ميزة | ابحث في جميع الميزات ({count})", + "features_filter_all": "الكل", + "features_filter_free": "مجاني", + "features_group_heading": "{heading} · {count}", + "features_no_match": "لا توجد ميزات تطابق بحثك", + "features_none": "لا توجد ميزات في هذه المجموعة", + "features_free_heading": "مجانية، ومشمولة مع كل ترخيص", + "features_new": "جديد بعد ترخيصك", + "features_filter_new": "جديد", "request_new_license": "طلب رخصة جديدة", "add_new_license_key": "إضافة مفتاح ترخيص جديد", "refresh_license_limits": "تحديث حدود الترخيص", @@ -29304,7 +29333,7 @@ "remove": "إزالة", "removeManyTitle": "إزالة {count} Collectors؟", "removeMessage": "يزيل هذا الصف فقط. المضيف الذي لا يزال يشغّل المجمّع سيظهر مجددًا عند نبضته التالية، لذا ألغِ تثبيته هناك أولًا.", - "removeOnlineMessage": "يزيل هذا الصف فقط. {count} من هذه المجمّعات متصل ويظهر مجددًا عند نبضته التالية؛ ألغِ تثبيته على مضيفه أولًا. | يزيل هذا الصفوف فقط. {count} من هذه المجمّعات متصلة وتظهر مجددًا عند نبضتها التالية؛ ألغِ تثبيتها على مضيفاتها أولًا.", + "removeOnlineMessage": "هذا يزيل الصف فقط. {count} من هذه المُجمِّعات متصلة وتعود عند نبضة القلب التالية، ما لم يكن رمز التسجيل الخاص بها مستنفدًا: عندها تبقى مخفية وتواصل إرسال البيانات. لذا ألغِ تثبيتها على مضيفها أولًا. | هذا يزيل الصفوف فقط. {count} من هذه المُجمِّعات متصلة وتعود عند نبضة القلب التالية، ما لم يكن رمز التسجيل الخاص بكل منها مستنفدًا: عندها تبقى مخفية وتواصل إرسال البيانات. لذا ألغِ تثبيتها على كل مضيف أولًا.", "removeTitle": "إزالة {name}؟", "removedCount": "تمت إزالة {count} Collector | تمت إزالة {count} Collectors", "rename": "إعادة التسمية", @@ -29314,6 +29343,7 @@ "restartManyTitle": "إعادة تشغيل {count} Collectors؟", "restartMessage": "يُعاد تشغيل كل Collector عند رسالته التالية من الخادم. يتوقف جمع البيانات لفترة وجيزة على كل مضيف.", "restartQueued": "طُلبت إعادة التشغيل لـ {count} Collector | طُلبت إعادة التشغيل لـ {count} Collectors", + "restartOffline": "هذا المُجمِّع غير متصل. أعد تشغيله بمجرد عودته للاتصال.", "restartUnsupported": "لا يقبل هذا الـ Collector أوامر إعادة التشغيل", "systemSections": "الأقسام التي يديرها النظام", "systemSectionsCaption": "امتداد OpAMP والقياس عن بُعد للخدمة، يضبطهما المشرف والخادم", @@ -29327,7 +29357,7 @@ "noVersion": "لا يوجد بعد", "members": "Collectors", "membersOnline": "{online} من {total} متصل", - "atDesired": "{count} من {total} على الإصدار المطلوب", + "atDesired": "تم تعيين الإصدار المطلوب لـ {count} من {total}", "changeVersion": "نشر", "deployVersion": "نشر إصدار", "deletedFleet": "أسطول محذوف", @@ -29442,7 +29472,7 @@ "confirmFixForward": "يفتح محرر {config}. انشر إصدارًا مصححًا وغيّر هذا الأسطول إليه؛ وعندها تُستبدل عملية الطرح هذه.", "confirmResume": "تتابع عملية الطرح نفسها من المرحلة {n}.", "confirmRollback": "يبدأ فورًا عملية طرح للعودة إلى الإصدار المستقر، {config} v{version}. لا تتلقى Collectors الموجودة عليه شيئًا.", - "confirmRollbackNoStable": "يبدأ فورًا عملية طرح للعودة إلى الإصدار المستقر.", + "confirmRollbackNoStable": "لا يمتلك هذا الأسطول إصدارًا مستقرًا، لذا ينتهي الطرح التدريجي وتتوقف مُجمِّعاته عن الجمع حتى تنشر مجددًا.", "confirmSkip": "يستبعد {count} Collector فاشلًا ويتابع. يُوسَم بأنه مستبعد ويُضمَّن مجددًا في عملية الطرح التالية. | يستبعد {count} Collectors فاشلة ويتابع. تُوسَم بأنها مستبعدة وتُضمَّن مجددًا في عملية الطرح التالية.", "confirmed": "تم التأكيد", "eventConverged": "تقاربت المرحلة {n}", @@ -29479,6 +29509,7 @@ "phaseN": "المرحلة {n}", "phaseTimedOut": "انتهت المهلة", "phaseTimeoutNote": "المرحلة التي لا تؤكد ولا ترفض خلال {minutes} د توقف عملية الطرح (إعداد الأسطول)", + "phaseTimeoutNoteSeconds": "تُوقف المرحلة التي لا تؤكد أو ترفض خلال {minutes} دقيقة و{seconds} ثانية عملية الطرح التدريجي (إعداد الأسطول)", "phaseVerifying": "قيد التحقق", "phases": "المراحل", "planEmpty": "لا يوجد أي جامع متصل، لذا ينتظر الطرح حتى يتصل أحدها.", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "وراثة ({value})", "offlineHeartbeats": "غير متصل بعد نبضات فائتة", "offlineHeartbeatsHelp": "يُعد الـ Collector غير متصل بعد هذا العدد من فواصل النبضات دون رسالة", - "offlineRatio": "حدث نسبة عدم الاتصال (%)", - "offlineRatioHelp": "يسجّل حدثًا للأسطول عندما تزيد نسبة Collectors غير المتصلة عن هذه النسبة", + "offlineRatio": "نسبة عدم الاتصال (%)", + "offlineRatioHelp": "تُوقف المرحلة عندما تتجاوز نسبة مُجمِّعاتها غير المتصلة هذه النسبة.", "outOfRange": "أدخل رقمًا من {min} إلى {max}", "phaseTimeout": "مهلة المرحلة (ثوانٍ)", "phaseTimeoutHelp": "المرحلة التي لا تؤكد ولا ترفض خلال هذه المدة توقف عملية الطرح", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} خطأ · النشر محظور | {count} أخطاء · النشر محظور", "saveNewFirst": "احفظ التكوين الجديد قبل النشر", "saveDraft": "حفظ المسودة", + "publishUnchanged": "هذا هو أحدث إصدار. عدّله لنشر إصدار جديد.", "publishVersion": "نشر الإصدار", "modeDraft": "تعديل المسودة", "modeRollingOut": "v{version} قيد الطرح", diff --git a/web/src/locales/languages/de-DE.json b/web/src/locales/languages/de-DE.json index 4728584664..05c0455415 100644 --- a/web/src/locales/languages/de-DE.json +++ b/web/src/locales/languages/de-DE.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Nicht in Ihrer Lizenz enthalten", + "title": "{feature} ist nicht in Ihrer Lizenz enthalten", + "description": "Ihr Administrator kann sie durch Aktualisieren der Lizenz hinzufügen, oder wenden Sie sich an den Vertrieb, um eine Lizenz zu erhalten, die sie enthält.", + "thisFeature": "Diese Funktion", + "contactSales": "Vertrieb kontaktieren", + "toastTitle": "Nicht in Ihrer Lizenz enthalten", + "toastMessage": "Ihre Lizenz enthält nicht: {features}. Bitten Sie Ihren Administrator, die Lizenz zu aktualisieren.", + "toastMessageGeneric": "Ihre Lizenz enthält diese Funktion nicht. Bitten Sie Ihren Administrator, die Lizenz zu aktualisieren.", + "bannerMessage": "Diese Funktion ist gesperrt. Dafür wird die Funktion {feature} in Ihrer Lizenz benötigt.", + "bannerMessageGeneric": "Diese Seite benötigt eine Funktion, die nicht in Ihrer Lizenz enthalten ist.", + "headerLocked": "Gesperrt: benötigt {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "Noch kein Verlauf", @@ -3407,6 +3420,22 @@ "contact_name": "Name des Ansprechpartners", "contact_email": "Kontakt-E-Mail", "environment_type": "Art der Umgebung", + "features": "Funktionen", + "features_all_unlocked": "Ihre Lizenz schaltet alle Funktionen frei.", + "features_summary": "Ihre Lizenz schaltet {ratio} frei. {free} kostenlose Funktion ist immer enthalten. | Ihre Lizenz schaltet {ratio} frei. {free} kostenlose Funktionen sind immer enthalten.", + "features_paid_ratio": "{unlocked} von {paid} kostenpflichtigen Funktionen | {unlocked} von {paid} kostenpflichtigen Funktionen", + "features_unlocked": "Freigeschaltet", + "features_missing": "Nicht in Ihrer Lizenz", + "features_request_access": "Zugriff anfordern", + "features_search": "{count} Funktion durchsuchen | Alle {count} Funktionen durchsuchen", + "features_filter_all": "Alle", + "features_filter_free": "Kostenlos", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Keine Funktionen entsprechen Ihrer Suche", + "features_none": "Keine Funktionen in dieser Gruppe", + "features_free_heading": "Kostenlos, in jeder Lizenz enthalten", + "features_new": "Neu seit Ihrer Lizenz", + "features_filter_new": "Neu", "request_new_license": "Neue Lizenz anfordern", "add_new_license_key": "Neuen Lizenzschlüssel hinzufügen", "refresh_license_limits": "Lizenzlimits aktualisieren", @@ -29304,7 +29333,7 @@ "remove": "Entfernen", "removeManyTitle": "{count} Collector entfernen?", "removeMessage": "Dadurch wird nur die Zeile entfernt. Ein Host, auf dem der Collector noch läuft, erscheint beim nächsten Heartbeat wieder; deinstallieren Sie ihn daher zuerst dort.", - "removeOnlineMessage": "Dadurch wird nur die Zeile entfernt. {count} dieser Collectors ist online und erscheint beim nächsten Heartbeat wieder; deinstallieren Sie ihn zuerst auf seinem Host. | Dadurch werden nur die Zeilen entfernt. {count} dieser Collectors sind online und erscheinen beim nächsten Heartbeat wieder; deinstallieren Sie sie zuerst auf ihren Hosts.", + "removeOnlineMessage": "Hiermit wird nur die Zeile entfernt. {count} dieser Collectors ist online und erscheint beim nächsten Heartbeat erneut, es sei denn, sein Enrollment-Token ist verbraucht: dann bleibt er ausgeblendet und sendet weiterhin Daten. Deinstallieren Sie ihn daher zuerst auf seinem Host. | Hiermit werden nur die Zeilen entfernt. {count} dieser Collectors sind online und erscheinen beim nächsten Heartbeat erneut, es sei denn, ihr Enrollment-Token ist verbraucht: dann bleiben sie ausgeblendet und senden weiterhin Daten. Deinstallieren Sie sie daher zuerst auf ihren Hosts.", "removeTitle": "{name} entfernen?", "removedCount": "{count} Collector entfernt | {count} Collector entfernt", "rename": "Umbenennen", @@ -29314,6 +29343,7 @@ "restartManyTitle": "{count} Collector neu starten?", "restartMessage": "Jeder Collector startet bei der nächsten Nachricht vom Server neu. Die Datenerfassung pausiert auf jedem Host kurz.", "restartQueued": "Neustart für {count} Collector angefordert | Neustart für {count} Collector angefordert", + "restartOffline": "Dieser Collector ist offline. Starten Sie ihn neu, sobald er wieder online ist.", "restartUnsupported": "Dieser Collector akzeptiert keine Neustart-Befehle", "systemSections": "Systemverwaltete Abschnitte", "systemSectionsCaption": "OpAMP-Erweiterung und Dienst-Telemetrie, vom Supervisor und vom Server festgelegt", @@ -29327,7 +29357,7 @@ "noVersion": "Noch keine", "members": "Collector", "membersOnline": "{online} von {total} online", - "atDesired": "{count} von {total} auf der Soll-Version", + "atDesired": "{count} von {total} der gewünschten Version zugewiesen", "changeVersion": "Bereitstellen", "deployVersion": "Version bereitstellen", "deletedFleet": "Gelöschtes Fleet", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Öffnet den Editor für {config}. Veröffentlichen Sie eine korrigierte Version und stellen Sie dieses Fleet darauf um; dieses Rollout wird dann abgelöst.", "confirmResume": "Dasselbe Rollout wird ab Phase {n} fortgesetzt.", "confirmRollback": "Startet sofort ein Rollout zurück auf die stabile Version, {config} v{version}. Collector, die sie bereits haben, erhalten nichts.", - "confirmRollbackNoStable": "Startet sofort ein Rollout zurück auf die stabile Version.", + "confirmRollbackNoStable": "Diese Fleet hat keine stabile Version, daher endet der Rollout und ihre Collectors stellen die Erfassung ein, bis Sie erneut bereitstellen.", "confirmSkip": "Schließt {count} fehlerhaften Collector aus und fährt fort. Er wird als ausgeschlossen markiert und im nächsten Rollout wieder einbezogen. | Schließt {count} fehlerhafte Collector aus und fährt fort. Sie werden als ausgeschlossen markiert und im nächsten Rollout wieder einbezogen.", "confirmed": "Bestätigt", "eventConverged": "Phase {n} konvergiert", @@ -29479,6 +29509,7 @@ "phaseN": "Phase {n}", "phaseTimedOut": "Zeitüberschreitung", "phaseTimeoutNote": "Eine Phase, die innerhalb von {minutes} Min. weder bestätigt noch ablehnt, hält das Rollout an (Fleet-Einstellung)", + "phaseTimeoutNoteSeconds": "Eine Phase, die innerhalb von {minutes} Min. {seconds} Sek. weder bestätigt noch abgelehnt wird, stoppt den Rollout (Fleet-Einstellung)", "phaseVerifying": "Wird überprüft", "phases": "Phasen", "planEmpty": "Kein Collector ist online, daher wartet der Rollout, bis sich einer verbindet", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Erben ({value})", "offlineHeartbeats": "Offline nach verpassten Heartbeats", "offlineHeartbeatsHelp": "Ein Collector gilt als offline, wenn so viele Heartbeat-Intervalle ohne Nachricht vergangen sind", - "offlineRatio": "Ereignis bei Offline-Anteil (%)", - "offlineRatioHelp": "Zeichnet ein Fleet-Ereignis auf, wenn mehr als dieser Anteil der Collector offline ist", + "offlineRatio": "Offline-Anteil (%)", + "offlineRatioHelp": "Stoppt die Phase, wenn mehr als dieser Anteil ihrer Collectors offline ist", "outOfRange": "Eine Zahl von {min} bis {max} eingeben", "phaseTimeout": "Phasen-Zeitlimit (Sekunden)", "phaseTimeoutHelp": "Ein Rollout, dessen Phase in dieser Zeit weder bestätigt noch ablehnt, wird angehalten", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} Fehler · Veröffentlichung blockiert | {count} Fehler · Veröffentlichung blockiert", "saveNewFirst": "Speichern Sie die neue Konfiguration vor dem Veröffentlichen", "saveDraft": "Entwurf speichern", + "publishUnchanged": "Dies ist die neueste Version. Bearbeiten Sie sie, um eine neue zu veröffentlichen.", "publishVersion": "Version veröffentlichen", "modeDraft": "Entwurf wird bearbeitet", "modeRollingOut": "v{version} wird ausgerollt", diff --git a/web/src/locales/languages/en-US.json b/web/src/locales/languages/en-US.json index c5c2baa8a5..453c870bd3 100644 --- a/web/src/locales/languages/en-US.json +++ b/web/src/locales/languages/en-US.json @@ -29331,7 +29331,7 @@ "remove": "Remove", "removeManyTitle": "Remove {count} collectors?", "removeMessage": "This removes the row only. A host that still runs the collector reappears on its next heartbeat, so uninstall it there first.", - "removeOnlineMessage": "This removes the row only. {count} of these collectors is online and reappears on its next heartbeat; uninstall it on its host first. | This removes the rows only. {count} of these collectors are online and reappear on their next heartbeat; uninstall them on their hosts first.", + "removeOnlineMessage": "This removes the row only. {count} of these collectors is online and reappears on its next heartbeat, unless its enrollment token is used up: then it stays hidden and keeps sending data. So uninstall it on its host first. | This removes the rows only. {count} of these collectors are online and reappear on their next heartbeat, unless their enrollment token is used up: then they stay hidden and keep sending data. So uninstall them on their hosts first.", "removeTitle": "Remove {name}?", "removedCount": "Removed {count} collector | Removed {count} collectors", "rename": "Rename", @@ -29355,7 +29355,7 @@ "noVersion": "None yet", "members": "Collectors", "membersOnline": "{online} of {total} online", - "atDesired": "{count} of {total} at the desired version", + "atDesired": "{count} of {total} assigned the desired version", "changeVersion": "Deploy", "deployVersion": "Deploy a version", "deletedFleet": "Deleted fleet", @@ -29757,6 +29757,7 @@ "publishBlockedChip": "{count} error · publish blocked | {count} errors · publish blocked", "saveNewFirst": "Save the new configuration before publishing", "saveDraft": "Save draft", + "publishUnchanged": "This is the latest version. Edit it to publish a new one.", "publishVersion": "Publish version", "modeDraft": "Editing draft", "modeRollingOut": "v{version} rolling out", diff --git a/web/src/locales/languages/es-ES.json b/web/src/locales/languages/es-ES.json index dba972bb27..025f5e4c7f 100644 --- a/web/src/locales/languages/es-ES.json +++ b/web/src/locales/languages/es-ES.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "No incluido en tu licencia", + "title": "{feature} no está incluido en tu licencia", + "description": "Tu administrador puede añadirlo actualizando la licencia, o contacta con ventas para obtener una licencia que lo incluya.", + "thisFeature": "Esta función", + "contactSales": "Contactar con ventas", + "toastTitle": "No incluido en tu licencia", + "toastMessage": "Tu licencia no incluye: {features}. Pide a tu administrador que actualice la licencia.", + "toastMessageGeneric": "Tu licencia no incluye esta función. Pide a tu administrador que actualice la licencia.", + "bannerMessage": "Esta función está bloqueada. Necesita la función {feature} en tu licencia.", + "bannerMessageGeneric": "Esta página necesita una función que no está en tu licencia.", + "headerLocked": "Bloqueada: necesita {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "Aún no hay historial", @@ -3407,6 +3420,22 @@ "contact_name": "Nombre de contacto", "contact_email": "Correo electrónico de contacto", "environment_type": "Tipo de entorno", + "features": "Funciones", + "features_all_unlocked": "Tu licencia desbloquea todas las funciones.", + "features_summary": "Tu licencia desbloquea {ratio}. {free} función gratuita siempre está incluida. | Tu licencia desbloquea {ratio}. {free} funciones gratuitas siempre están incluidas.", + "features_paid_ratio": "{unlocked} de {paid} función de pago | {unlocked} de {paid} funciones de pago", + "features_unlocked": "Desbloqueada", + "features_missing": "No incluida en tu licencia", + "features_request_access": "Solicitar acceso", + "features_search": "Buscar {count} función | Buscar las {count} funciones", + "features_filter_all": "Todas", + "features_filter_free": "Gratuitas", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Ninguna función coincide con tu búsqueda", + "features_none": "No hay funciones en este grupo", + "features_free_heading": "Gratuitas, incluidas en todas las licencias", + "features_new": "Nuevas posteriores a tu licencia", + "features_filter_new": "Nuevas", "request_new_license": "Solicitar una nueva licencia", "add_new_license_key": "Agregar nueva clave de licencia", "refresh_license_limits": "Actualizar los límites de la licencia", @@ -29304,7 +29333,7 @@ "remove": "Quitar", "removeManyTitle": "¿Quitar {count} colectores?", "removeMessage": "Esto elimina solo la fila. Un host que siga ejecutando el colector volverá a aparecer en su próximo latido, así que desinstálalo allí primero.", - "removeOnlineMessage": "Esto elimina solo la fila. {count} de estos colectores está en línea y volverá a aparecer en su próximo latido; desinstálalo en su host primero. | Esto elimina solo las filas. {count} de estos colectores están en línea y volverán a aparecer en su próximo latido; desinstálalos en sus hosts primero.", + "removeOnlineMessage": "Esto solo elimina la fila. {count} de estos colectores está en línea y reaparece en su próximo latido, a menos que su token de inscripción se haya agotado: en ese caso, permanece oculto y sigue enviando datos. Así que primero desinstálalo en su host. | Esto solo elimina las filas. {count} de estos colectores están en línea y reaparecen en su próximo latido, a menos que su token de inscripción se haya agotado: en ese caso, permanecen ocultos y siguen enviando datos. Así que primero desinstálalos en sus hosts.", "removeTitle": "¿Quitar {name}?", "removedCount": "Se quitó {count} colector | Se quitaron {count} colectores", "rename": "Renombrar", @@ -29314,6 +29343,7 @@ "restartManyTitle": "¿Reiniciar {count} colectores?", "restartMessage": "Cada colector se reinicia con su próximo mensaje del servidor. La recopilación de datos se detiene brevemente en cada host.", "restartQueued": "Reinicio solicitado para {count} colector | Reinicio solicitado para {count} colectores", + "restartOffline": "Este colector está desconectado. Reinícialo cuando vuelva a estar disponible.", "restartUnsupported": "Este colector no admite comandos de reinicio", "systemSections": "Secciones gestionadas por el sistema", "systemSectionsCaption": "Extensión de OpAMP y telemetría del servicio, definidas por el supervisor y el servidor", @@ -29327,7 +29357,7 @@ "noVersion": "Ninguna aún", "members": "Colectores", "membersOnline": "{online} de {total} en línea", - "atDesired": "{count} de {total} en la versión deseada", + "atDesired": "{count} de {total} tienen asignada la versión deseada", "changeVersion": "Desplegar", "deployVersion": "Desplegar una versión", "deletedFleet": "Flota eliminada", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Abre el editor de {config}. Publica una versión corregida y cambia esta flota a ella; este despliegue queda entonces reemplazado.", "confirmResume": "El mismo despliegue continúa desde la fase {n}.", "confirmRollback": "Inicia un despliegue inmediato de vuelta a la versión estable, {config} v{version}. Los colectores que ya la tienen no reciben nada.", - "confirmRollbackNoStable": "Inicia un despliegue inmediato de vuelta a la versión estable.", + "confirmRollbackNoStable": "Esta flota no tiene ninguna versión estable, por lo que el despliegue finaliza y sus colectores dejan de recopilar hasta que vuelvas a desplegar.", "confirmSkip": "Excluye {count} colector con fallos y continúa. Se marca como excluido y se vuelve a incluir en el siguiente despliegue. | Excluye {count} colectores con fallos y continúa. Se marcan como excluidos y se vuelven a incluir en el siguiente despliegue.", "confirmed": "Confirmado", "eventConverged": "La fase {n} convergió", @@ -29479,6 +29509,7 @@ "phaseN": "Fase {n}", "phaseTimedOut": "Tiempo agotado", "phaseTimeoutNote": "Una fase que no confirma ni rechaza en {minutes} min detiene el despliegue (ajuste de la flota)", + "phaseTimeoutNoteSeconds": "Una fase que no confirme ni rechace en {minutes} min {seconds} s detiene el despliegue (ajuste de la flota)", "phaseVerifying": "Verificando", "phases": "Fases", "planEmpty": "No hay ningún colector en línea, así que el despliegue esperará hasta que se conecte uno", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Heredar ({value})", "offlineHeartbeats": "Sin conexión tras latidos perdidos", "offlineHeartbeatsHelp": "Un colector está sin conexión tras este número de intervalos de latido sin mensaje", - "offlineRatio": "Evento de proporción sin conexión (%)", - "offlineRatioHelp": "Registra un evento de flota cuando más de esta proporción de colectores está sin conexión", + "offlineRatio": "Proporción de desconectados (%)", + "offlineRatioHelp": "Detiene la fase cuando más de esta proporción de sus colectores está desconectada", "outOfRange": "Introduce un número de {min} a {max}", "phaseTimeout": "Tiempo de espera de la fase (segundos)", "phaseTimeoutHelp": "Una fase del despliegue que no confirma ni rechaza en este tiempo se detiene", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} error · publicación bloqueada | {count} errores · publicación bloqueada", "saveNewFirst": "Guarda la nueva configuración antes de publicar", "saveDraft": "Guardar borrador", + "publishUnchanged": "Esta es la versión más reciente. Edítala para publicar una nueva.", "publishVersion": "Publicar versión", "modeDraft": "Editando borrador", "modeRollingOut": "v{version} en despliegue", diff --git a/web/src/locales/languages/fr-FR.json b/web/src/locales/languages/fr-FR.json index 4dec75399c..afede379ad 100644 --- a/web/src/locales/languages/fr-FR.json +++ b/web/src/locales/languages/fr-FR.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Non inclus dans votre licence", + "title": "{feature} n'est pas couvert par votre licence", + "description": "Votre administrateur peut l'ajouter en mettant à jour la licence, ou contactez le service commercial pour obtenir une licence qui l'inclut.", + "thisFeature": "Cette fonctionnalité", + "contactSales": "Contacter le service commercial", + "toastTitle": "Non inclus dans votre licence", + "toastMessage": "Votre licence n'inclut pas : {features}. Demandez à votre administrateur de mettre à jour la licence.", + "toastMessageGeneric": "Votre licence n'inclut pas cette fonctionnalité. Demandez à votre administrateur de mettre à jour la licence.", + "bannerMessage": "Cette fonctionnalité est verrouillée. Elle nécessite la fonctionnalité {feature} dans votre licence.", + "bannerMessageGeneric": "Cette page nécessite une fonctionnalité absente de votre licence.", + "headerLocked": "Verrouillé : nécessite {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "Aucun historique pour le moment", @@ -3407,6 +3420,22 @@ "contact_name": "Nom du contact", "contact_email": "E-mail de contact", "environment_type": "Type d'environnement", + "features": "Fonctionnalités", + "features_all_unlocked": "Votre licence déverrouille toutes les fonctionnalités.", + "features_summary": "Votre licence déverrouille {ratio}. {free} fonctionnalité gratuite est toujours incluse. | Votre licence déverrouille {ratio}. {free} fonctionnalités gratuites sont toujours incluses.", + "features_paid_ratio": "{unlocked} sur {paid} fonctionnalité payante | {unlocked} sur {paid} fonctionnalités payantes", + "features_unlocked": "Déverrouillé", + "features_missing": "Non inclus dans votre licence", + "features_request_access": "Demander l'accès", + "features_search": "Rechercher dans {count} fonctionnalité | Rechercher dans toutes les {count} fonctionnalités", + "features_filter_all": "Toutes", + "features_filter_free": "Gratuites", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Aucune fonctionnalité ne correspond à votre recherche", + "features_none": "Aucune fonctionnalité dans ce groupe", + "features_free_heading": "Gratuites, incluses avec chaque licence", + "features_new": "Nouvelles depuis votre licence", + "features_filter_new": "Nouvelles", "request_new_license": "Demander une nouvelle licence", "add_new_license_key": "Ajouter une nouvelle clé de licence", "refresh_license_limits": "Actualiser les limites de licence", @@ -29304,7 +29333,7 @@ "remove": "Supprimer", "removeManyTitle": "Supprimer {count} collecteurs ?", "removeMessage": "Cela supprime uniquement la ligne. Un hôte qui exécute encore le collecteur réapparaît à son prochain signal de présence ; désinstallez-le d'abord sur cet hôte.", - "removeOnlineMessage": "Cela supprime uniquement la ligne. {count} de ces collecteurs est en ligne et réapparaît à son prochain signal de présence ; désinstallez-le d'abord sur son hôte. | Cela supprime uniquement les lignes. {count} de ces collecteurs sont en ligne et réapparaissent à leur prochain signal de présence ; désinstallez-les d'abord sur leurs hôtes.", + "removeOnlineMessage": "Cela supprime uniquement la ligne. {count} de ces collecteurs est en ligne et réapparaît à son prochain battement de cœur, sauf si son jeton d'enrôlement est épuisé : dans ce cas, il reste masqué et continue d'envoyer des données. Désinstallez-le donc d'abord sur son hôte. | Cela supprime uniquement les lignes. {count} de ces collecteurs sont en ligne et réapparaissent à leur prochain battement de cœur, sauf si leur jeton d'enrôlement est épuisé : dans ce cas, ils restent masqués et continuent d'envoyer des données. Désinstallez-les donc d'abord sur leurs hôtes.", "removeTitle": "Supprimer {name} ?", "removedCount": "{count} collecteur supprimé | {count} collecteurs supprimés", "rename": "Renommer", @@ -29314,6 +29343,7 @@ "restartManyTitle": "Redémarrer {count} collecteurs ?", "restartMessage": "Chaque collecteur redémarre à son prochain message du serveur. La collecte de données est brièvement interrompue sur chaque hôte.", "restartQueued": "Redémarrage demandé pour {count} collecteur | Redémarrage demandé pour {count} collecteurs", + "restartOffline": "Ce collecteur est hors ligne. Redémarrez-le lorsqu'il sera de nouveau en ligne.", "restartUnsupported": "Ce collecteur n'accepte pas les commandes de redémarrage", "systemSections": "Sections gérées par le système", "systemSectionsCaption": "Extension OpAMP et télémétrie du service, définies par le superviseur et le serveur", @@ -29327,7 +29357,7 @@ "noVersion": "Aucune pour le moment", "members": "Collecteurs", "membersOnline": "{online} sur {total} en ligne", - "atDesired": "{count} sur {total} à la version souhaitée", + "atDesired": "{count} sur {total} ont la version souhaitée", "changeVersion": "Déployer", "deployVersion": "Déployer une version", "deletedFleet": "Flotte supprimée", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Ouvre l'éditeur de {config}. Publiez une version corrigée et faites-y passer cette flotte ; ce déploiement est alors remplacé.", "confirmResume": "Le même déploiement reprend à la phase {n}.", "confirmRollback": "Lance immédiatement un déploiement de retour à la version stable, {config} v{version}. Les collecteurs qui l'utilisent déjà ne reçoivent rien.", - "confirmRollbackNoStable": "Lance immédiatement un déploiement de retour à la version stable.", + "confirmRollbackNoStable": "Cette flotte n'a pas de version stable, donc le déploiement se termine et ses collecteurs cessent de collecter jusqu'à ce que vous redéployiez.", "confirmSkip": "Exclut {count} collecteur en échec et continue. Il est marqué comme exclu et inclus de nouveau au prochain déploiement. | Exclut {count} collecteurs en échec et continue. Ils sont marqués comme exclus et inclus de nouveau au prochain déploiement.", "confirmed": "Confirmé", "eventConverged": "Phase {n} convergée", @@ -29479,6 +29509,7 @@ "phaseN": "Phase {n}", "phaseTimedOut": "Délai dépassé", "phaseTimeoutNote": "Une phase qui ne confirme ni ne rejette en {minutes} min interrompt le déploiement (paramètre de la flotte)", + "phaseTimeoutNoteSeconds": "Une phase qui ne confirme ni ne rejette dans un délai de {minutes} min {seconds} s interrompt le déploiement (réglage de la flotte)", "phaseVerifying": "Vérification", "phases": "Phases", "planEmpty": "Aucun collecteur n'est en ligne, le déploiement attend qu'un collecteur se connecte", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Hérité ({value})", "offlineHeartbeats": "Hors ligne après des heartbeats manqués", "offlineHeartbeatsHelp": "Un collecteur est hors ligne après ce nombre d'intervalles de heartbeat sans message", - "offlineRatio": "Événement de ratio hors ligne (%)", - "offlineRatioHelp": "Enregistre un événement de flotte lorsque plus de cette part de collecteurs est hors ligne", + "offlineRatio": "Taux hors ligne (%)", + "offlineRatioHelp": "Interrompt la phase lorsque la proportion de ses collecteurs hors ligne dépasse ce seuil", "outOfRange": "Saisissez un nombre de {min} à {max}", "phaseTimeout": "Délai d'une phase (secondes)", "phaseTimeoutHelp": "Une phase de déploiement qui ne confirme ni ne rejette dans ce délai est interrompue", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} erreur · publication bloquée | {count} erreurs · publication bloquée", "saveNewFirst": "Enregistrez la nouvelle configuration avant de publier", "saveDraft": "Enregistrer le brouillon", + "publishUnchanged": "Il s'agit de la dernière version. Modifiez-la pour en publier une nouvelle.", "publishVersion": "Publier la version", "modeDraft": "Modification du brouillon", "modeRollingOut": "v{version} en cours de déploiement", diff --git a/web/src/locales/languages/it-IT.json b/web/src/locales/languages/it-IT.json index 1795bed810..f2a52d1f3b 100644 --- a/web/src/locales/languages/it-IT.json +++ b/web/src/locales/languages/it-IT.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Non incluso nella tua licenza", + "title": "{feature} non è incluso nella tua licenza", + "description": "Il tuo amministratore può aggiungerlo aggiornando la licenza, oppure contatta il reparto commerciale per ottenere una licenza che lo includa.", + "thisFeature": "Questa funzionalità", + "contactSales": "Contatta il reparto commerciale", + "toastTitle": "Non incluso nella tua licenza", + "toastMessage": "La tua licenza non include: {features}. Chiedi al tuo amministratore di aggiornare la licenza.", + "toastMessageGeneric": "La tua licenza non include questa funzionalità. Chiedi al tuo amministratore di aggiornare la licenza.", + "bannerMessage": "Questa funzionalità è bloccata. Richiede la funzionalità {feature} nella tua licenza.", + "bannerMessageGeneric": "Questa pagina richiede una funzionalità non inclusa nella tua licenza.", + "headerLocked": "Bloccata: richiede {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "Nessuna cronologia ancora", @@ -3407,6 +3420,22 @@ "contact_name": "Nome del contatto", "contact_email": "Email di contatto", "environment_type": "Tipo di ambiente", + "features": "Funzionalità", + "features_all_unlocked": "La tua licenza sblocca tutte le funzionalità.", + "features_summary": "La tua licenza sblocca {ratio}. {free} funzionalità gratuita è sempre inclusa. | La tua licenza sblocca {ratio}. {free} funzionalità gratuite sono sempre incluse.", + "features_paid_ratio": "{unlocked} di {paid} funzionalità a pagamento | {unlocked} di {paid} funzionalità a pagamento", + "features_unlocked": "Sbloccata", + "features_missing": "Non incluso nella tua licenza", + "features_request_access": "Richiedi accesso", + "features_search": "Cerca {count} funzionalità | Cerca tutte le {count} funzionalità", + "features_filter_all": "Tutte", + "features_filter_free": "Gratuite", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Nessuna funzionalità corrisponde alla tua ricerca", + "features_none": "Nessuna funzionalità in questo gruppo", + "features_free_heading": "Gratuite, incluse in ogni licenza", + "features_new": "Nuove dopo la tua licenza", + "features_filter_new": "Nuove", "request_new_license": "Richiedi una nuova licenza", "add_new_license_key": "Aggiungi nuova chiave di licenza", "refresh_license_limits": "Aggiorna i limiti delle licenze", @@ -29304,7 +29333,7 @@ "remove": "Rimuovi", "removeManyTitle": "Rimuovere {count} collector?", "removeMessage": "Questa operazione rimuove solo la riga. Un host che esegue ancora il collector ricompare al suo prossimo heartbeat, quindi disinstallalo prima da lì.", - "removeOnlineMessage": "Questa operazione rimuove solo la riga. {count} di questi collector è online e ricompare al suo prossimo heartbeat; disinstallalo prima sul suo host. | Questa operazione rimuove solo le righe. {count} di questi collector sono online e ricompaiono al loro prossimo heartbeat; disinstallali prima sui loro host.", + "removeOnlineMessage": "Questo rimuove solo la riga. {count} di questi collector è online e riappare al prossimo heartbeat, a meno che il suo token di registrazione non sia esaurito: in tal caso resta nascosto e continua a inviare dati. Quindi disinstallalo prima sul suo host. | Questo rimuove solo le righe. {count} di questi collector sono online e riappaiono al prossimo heartbeat, a meno che il loro token di registrazione non sia esaurito: in tal caso restano nascosti e continuano a inviare dati. Quindi disinstallali prima sui loro host.", "removeTitle": "Rimuovere {name}?", "removedCount": "Rimosso {count} collector | Rimossi {count} collector", "rename": "Rinomina", @@ -29314,6 +29343,7 @@ "restartManyTitle": "Riavviare {count} collector?", "restartMessage": "Ogni collector si riavvia al suo prossimo messaggio dal server. La raccolta dei dati si interrompe brevemente su ogni host.", "restartQueued": "Riavvio richiesto per {count} collector | Riavvio richiesto per {count} collector", + "restartOffline": "Questo collector è offline. Riavvialo quando torna online.", "restartUnsupported": "Questo collector non accetta comandi di riavvio", "systemSections": "Sezioni gestite dal sistema", "systemSectionsCaption": "Estensione OpAMP e telemetria del servizio, impostate dal supervisor e dal server", @@ -29327,7 +29357,7 @@ "noVersion": "Ancora nessuna", "members": "Collector", "membersOnline": "{online} di {total} online", - "atDesired": "{count} di {total} alla versione desiderata", + "atDesired": "{count} di {total} con versione desiderata assegnata", "changeVersion": "Distribuisci", "deployVersion": "Distribuisci una versione", "deletedFleet": "Fleet eliminato", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Apre l'editor di {config}. Pubblica una versione corretta e porta questo fleet su di essa; questo rollout viene quindi sostituito.", "confirmResume": "Lo stesso rollout continua dalla fase {n}.", "confirmRollback": "Avvia subito un rollout di ritorno alla versione stabile, {config} v{version}. I collector che la eseguono già non ricevono nulla.", - "confirmRollbackNoStable": "Avvia subito un rollout di ritorno alla versione stabile.", + "confirmRollbackNoStable": "Questa flotta non ha una versione stabile, quindi il rollout termina e i suoi collector smettono di raccogliere dati finché non esegui di nuovo il deploy.", "confirmSkip": "Esclude {count} collector in errore e continua. Viene contrassegnato come escluso e reincluso nel prossimo rollout. | Esclude {count} collector in errore e continua. Vengono contrassegnati come esclusi e reinclusi nel prossimo rollout.", "confirmed": "Confermato", "eventConverged": "Fase {n} convergente", @@ -29479,6 +29509,7 @@ "phaseN": "Fase {n}", "phaseTimedOut": "Scaduta", "phaseTimeoutNote": "Una fase che non conferma né rifiuta entro {minutes} min interrompe il rollout (impostazione del fleet)", + "phaseTimeoutNoteSeconds": "Una fase che non conferma né rifiuta entro {minutes} min {seconds} s interrompe il rollout (impostazione della flotta)", "phaseVerifying": "In verifica", "phases": "Fasi", "planEmpty": "Nessun collector è online, quindi il rollout attende che uno si connetta", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Eredita ({value})", "offlineHeartbeats": "Offline dopo heartbeat mancati", "offlineHeartbeatsHelp": "Un collector è offline dopo questo numero di intervalli di heartbeat senza alcun messaggio", - "offlineRatio": "Evento di quota offline (%)", - "offlineRatioHelp": "Registra un evento del fleet quando più di questa quota di collector è offline", + "offlineRatio": "Percentuale offline (%)", + "offlineRatioHelp": "Interrompe la fase quando più di questa quota dei suoi collector è offline", "outOfRange": "Inserisci un numero da {min} a {max}", "phaseTimeout": "Timeout della fase (secondi)", "phaseTimeoutHelp": "Una fase del rollout che non conferma né rifiuta entro questo tempo viene interrotta", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} errore · pubblicazione bloccata | {count} errori · pubblicazione bloccata", "saveNewFirst": "Salva la nuova configurazione prima di pubblicare", "saveDraft": "Salva bozza", + "publishUnchanged": "Questa è la versione più recente. Modificala per pubblicarne una nuova.", "publishVersion": "Pubblica versione", "modeDraft": "Modifica della bozza", "modeRollingOut": "v{version} in distribuzione", diff --git a/web/src/locales/languages/ja-JP.json b/web/src/locales/languages/ja-JP.json index 0d76eb3f0c..ad4daca591 100644 --- a/web/src/locales/languages/ja-JP.json +++ b/web/src/locales/languages/ja-JP.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "ライセンスに含まれていません", + "title": "{feature} はライセンスに含まれていません", + "description": "管理者がライセンスを更新して追加するか、これを含むライセンスを取得するには営業担当者にお問い合わせください。", + "thisFeature": "この機能", + "contactSales": "営業担当者に問い合わせる", + "toastTitle": "ライセンスに含まれていません", + "toastMessage": "お使いのライセンスには以下が含まれていません: {features}。管理者にライセンスの更新を依頼してください。", + "toastMessageGeneric": "お使いのライセンスにはこの機能が含まれていません。管理者にライセンスの更新を依頼してください。", + "bannerMessage": "この機能はロックされています。ライセンスに {feature} 機能が必要です。", + "bannerMessageGeneric": "このページには、ライセンスに含まれていない機能が必要です。", + "headerLocked": "ロック中: {feature} が必要" + }, "emptyState": { "illustrations": { "noHistoryYet": "履歴はまだありません", @@ -3407,6 +3420,22 @@ "contact_name": "連絡先名", "contact_email": "連絡先電子メール", "environment_type": "環境タイプ", + "features": "機能", + "features_all_unlocked": "お使いのライセンスですべての機能が利用できます。", + "features_summary": "ライセンスで {ratio} が利用可能です。{free} 個の無料機能が常に含まれます。 | ライセンスで {ratio} が利用可能です。{free} 個の無料機能が常に含まれます。", + "features_paid_ratio": "有償機能 {unlocked}/{paid} | 有償機能 {unlocked}/{paid}", + "features_unlocked": "利用可能", + "features_missing": "ライセンスに含まれていません", + "features_request_access": "アクセス権をリクエスト", + "features_search": "{count} 個の機能を検索 | 全 {count} 個の機能を検索", + "features_filter_all": "すべて", + "features_filter_free": "無料", + "features_group_heading": "{heading} · {count} 件", + "features_no_match": "検索に一致する機能はありません", + "features_none": "このグループに機能はありません", + "features_free_heading": "無料: すべてのライセンスに含まれます", + "features_new": "ライセンス以降の新機能", + "features_filter_new": "新規", "request_new_license": "新しいライセンスをリクエスト", "add_new_license_key": "新しいライセンスキーを追加", "refresh_license_limits": "ライセンス制限を更新", @@ -29304,7 +29333,7 @@ "remove": "削除", "removeManyTitle": "{count} 台のコレクターを削除しますか?", "removeMessage": "これは行を削除するだけです。コレクターがまだ実行されているホストは次回のハートビートで再表示されるため、先にそのホストでアンインストールしてください。", - "removeOnlineMessage": "これは行を削除するだけです。これらのコレクターのうち {count} 個がオンラインで、次回のハートビートで再表示されます。先にそのホストでアンインストールしてください。 | これは行を削除するだけです。これらのコレクターのうち {count} 個がオンラインで、次回のハートビートで再表示されます。先にそのホストでアンインストールしてください。", + "removeOnlineMessage": "これは行を削除するだけです。これらのコレクターのうち {count} 台がオンラインで、次回のハートビート時に再表示されます。ただし、登録トークンが使い切られている場合は、非表示のままデータを送信し続けます。そのため、先にホスト上でアンインストールしてください。 | これは行を削除するだけです。これらのコレクターのうち {count} 台がオンラインで、次回のハートビート時に再表示されます。ただし、登録トークンが使い切られている場合は、非表示のままデータを送信し続けます。そのため、先に各ホスト上でアンインストールしてください。", "removeTitle": "{name} を削除しますか?", "removedCount": "{count} 台のコレクターを削除しました | {count} 台のコレクターを削除しました", "rename": "名前を変更", @@ -29314,6 +29343,7 @@ "restartManyTitle": "{count} 台のコレクターを再起動しますか?", "restartMessage": "各コレクターは、サーバーからの次のメッセージで再起動します。各ホストでデータ収集が一時的に停止します。", "restartQueued": "{count} 台のコレクターの再起動をリクエストしました | {count} 台のコレクターの再起動をリクエストしました", + "restartOffline": "このコレクターはオフラインです。オンラインに戻ったら再起動してください。", "restartUnsupported": "このコレクターは再起動コマンドに対応していません", "systemSections": "システム管理セクション", "systemSectionsCaption": "OpAMP 拡張とサービステレメトリ。スーパーバイザーとサーバーが設定します", @@ -29327,7 +29357,7 @@ "noVersion": "まだありません", "members": "コレクター", "membersOnline": "{total} 台中 {online} 台がオンライン", - "atDesired": "{total} 台中 {count} 台が目標バージョン", + "atDesired": "{count} / {total} に希望のバージョンを割り当て済み", "changeVersion": "デプロイ", "deployVersion": "バージョンをデプロイ", "deletedFleet": "削除されたフリート", @@ -29442,7 +29472,7 @@ "confirmFixForward": "{config} のエディターを開きます。修正版を公開し、このフリートをそのバージョンに変更してください。このロールアウトは置き換えられます。", "confirmResume": "同じロールアウトがフェーズ {n} から続行されます。", "confirmRollback": "安定バージョン {config} v{version} への即時ロールアウトを開始します。すでにそのバージョンのコレクターには何も送信されません。", - "confirmRollbackNoStable": "安定バージョンへの即時ロールアウトを開始します。", + "confirmRollbackNoStable": "この Fleet には安定バージョンがないため、ロールアウトは終了し、再度デプロイするまでコレクターは収集を停止します。", "confirmSkip": "失敗している {count} 台のコレクターを除外して続行します。除外済みとしてマークされ、次のロールアウトで再び対象になります。 | 失敗している {count} 台のコレクターを除外して続行します。除外済みとしてマークされ、次のロールアウトで再び対象になります。", "confirmed": "確認済み", "eventConverged": "フェーズ {n} が収束", @@ -29479,6 +29509,7 @@ "phaseN": "フェーズ {n}", "phaseTimedOut": "タイムアウト", "phaseTimeoutNote": "{minutes} 分以内に承認も拒否もされないフェーズがあると、ロールアウトは停止します(フリート設定)", + "phaseTimeoutNoteSeconds": "{minutes} 分 {seconds} 秒以内に確認も拒否もされないフェーズは、ロールアウトを停止します(Fleet 設定)", "phaseVerifying": "検証中", "phases": "フェーズ", "planEmpty": "オンラインのコレクターがないため、コレクターが接続するまでロールアウトは待機します。", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "継承({value})", "offlineHeartbeats": "オフラインと判定するハートビート欠落回数", "offlineHeartbeatsHelp": "メッセージがないままこの回数のハートビート間隔が経過すると、コレクターはオフラインとみなされます", - "offlineRatio": "オフライン率イベント(%)", - "offlineRatioHelp": "オフラインのコレクターの割合がこの値を超えると、フリートイベントを記録します", + "offlineRatio": "オフライン率 (%)", + "offlineRatioHelp": "コレクターのうちオフラインの割合がこの値を超えると、フェーズを停止します", "outOfRange": "{min} から {max} までの数値を入力してください", "phaseTimeout": "フェーズのタイムアウト(秒)", "phaseTimeoutHelp": "この時間内に承認も拒否もされないロールアウトフェーズがあると、停止します", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "エラー {count} 件 · 公開不可 | エラー {count} 件 · 公開不可", "saveNewFirst": "公開する前に新しい構成を保存してください", "saveDraft": "下書きを保存", + "publishUnchanged": "これは最新バージョンです。新しいバージョンを公開するには編集してください。", "publishVersion": "バージョンを公開", "modeDraft": "下書きを編集中", "modeRollingOut": "v{version} をロールアウト中", diff --git a/web/src/locales/languages/ko-KR.json b/web/src/locales/languages/ko-KR.json index 522032e266..a5f666dc32 100644 --- a/web/src/locales/languages/ko-KR.json +++ b/web/src/locales/languages/ko-KR.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "라이선스에 없음", + "title": "라이선스에 {feature}이(가) 포함되어 있지 않습니다", + "description": "관리자가 라이선스를 업데이트하여 추가할 수 있으며, 해당 기능이 포함된 라이선스를 받으려면 영업팀에 문의하세요.", + "thisFeature": "이 기능", + "contactSales": "영업팀 문의", + "toastTitle": "라이선스에 포함되지 않음", + "toastMessage": "라이선스에 다음이 포함되어 있지 않습니다: {features}. 관리자에게 라이선스 업데이트를 요청하세요.", + "toastMessageGeneric": "라이선스에 이 기능이 포함되어 있지 않습니다. 관리자에게 라이선스 업데이트를 요청하세요.", + "bannerMessage": "이 기능은 잠겨 있습니다. 라이선스에 {feature} 기능이 필요합니다.", + "bannerMessageGeneric": "이 페이지에는 라이선스에 없는 기능이 필요합니다.", + "headerLocked": "잠김: {feature} 필요" + }, "emptyState": { "illustrations": { "noHistoryYet": "아직 기록이 없습니다", @@ -3407,6 +3420,22 @@ "contact_name": "담당자 이름", "contact_email": "연락처 이메일", "environment_type": "환경 유형", + "features": "기능", + "features_all_unlocked": "라이선스로 모든 기능을 사용할 수 있습니다.", + "features_summary": "라이선스로 {ratio}을(를) 사용할 수 있습니다. {free}개의 무료 기능은 항상 포함됩니다. | 라이선스로 {ratio}을(를) 사용할 수 있습니다. {free}개의 무료 기능은 항상 포함됩니다.", + "features_paid_ratio": "{paid}개 유료 기능 중 {unlocked}개 | {paid}개 유료 기능 중 {unlocked}개", + "features_unlocked": "사용 가능", + "features_missing": "라이선스에 없음", + "features_request_access": "액세스 요청", + "features_search": "기능 {count}개 검색 | 전체 기능 {count}개 검색", + "features_filter_all": "전체", + "features_filter_free": "무료", + "features_group_heading": "{heading} · {count}", + "features_no_match": "검색과 일치하는 기능이 없습니다", + "features_none": "이 그룹에 기능이 없습니다", + "features_free_heading": "무료, 모든 라이선스에 포함", + "features_new": "라이선스 이후 추가된 기능", + "features_filter_new": "신규", "request_new_license": "새 라이선스 요청", "add_new_license_key": "새 라이선스 키 추가", "refresh_license_limits": "라이선스 제한 새로고침", @@ -29304,7 +29333,7 @@ "remove": "제거", "removeManyTitle": "수집기 {count}개를 제거하시겠습니까?", "removeMessage": "이 작업은 행만 제거합니다. 컬렉터가 계속 실행 중인 호스트는 다음 하트비트에 다시 나타나므로, 먼저 해당 호스트에서 컬렉터를 제거하세요.", - "removeOnlineMessage": "이 작업은 행만 제거합니다. 이 컬렉터 중 {count}개가 온라인 상태이며 다음 하트비트에 다시 나타나므로, 먼저 해당 호스트에서 제거하세요. | 이 작업은 행만 제거합니다. 이 컬렉터 중 {count}개가 온라인 상태이며 다음 하트비트에 다시 나타나므로, 먼저 해당 호스트에서 제거하세요.", + "removeOnlineMessage": "이 작업은 행만 제거합니다. 이 수집기 중 {count}개는 온라인 상태이며 다음 하트비트에서 다시 나타납니다. 단, 등록 토큰이 소진된 경우에는 숨겨진 상태로 남아 계속 데이터를 전송합니다. 따라서 먼저 해당 호스트에서 수집기를 제거하세요. | 이 작업은 행만 제거합니다. 이 수집기 중 {count}개는 온라인 상태이며 다음 하트비트에서 다시 나타납니다. 단, 등록 토큰이 소진된 경우에는 숨겨진 상태로 남아 계속 데이터를 전송합니다. 따라서 먼저 해당 호스트에서 수집기를 제거하세요.", "removeTitle": "{name}을(를) 제거하시겠습니까?", "removedCount": "수집기 {count}개 제거됨 | 수집기 {count}개 제거됨", "rename": "이름 변경", @@ -29314,6 +29343,7 @@ "restartManyTitle": "수집기 {count}개를 재시작하시겠습니까?", "restartMessage": "각 수집기는 서버의 다음 메시지를 받을 때 재시작됩니다. 각 호스트에서 데이터 수집이 잠시 중단됩니다.", "restartQueued": "수집기 {count}개에 재시작이 요청되었습니다 | 수집기 {count}개에 재시작이 요청되었습니다", + "restartOffline": "이 수집기는 오프라인입니다. 다시 연결되면 재시작하세요.", "restartUnsupported": "이 수집기는 재시작 명령을 지원하지 않습니다", "systemSections": "시스템 관리 섹션", "systemSectionsCaption": "슈퍼바이저와 서버가 설정하는 OpAMP 확장 및 서비스 텔레메트리", @@ -29327,7 +29357,7 @@ "noVersion": "아직 없음", "members": "수집기", "membersOnline": "{total}개 중 {online}개 온라인", - "atDesired": "{total}개 중 {count}개가 목표 버전", + "atDesired": "{count}개(총 {total}개)가 원하는 버전으로 할당됨", "changeVersion": "배포", "deployVersion": "버전 배포", "deletedFleet": "삭제된 플릿", @@ -29442,7 +29472,7 @@ "confirmFixForward": "{config} 편집기를 엽니다. 수정된 버전을 게시하고 이 플릿을 해당 버전으로 변경하면 이 롤아웃은 대체됩니다.", "confirmResume": "동일한 롤아웃이 {n}단계부터 계속됩니다.", "confirmRollback": "안정 버전인 {config} v{version}(으)로 즉시 롤백하는 롤아웃을 시작합니다. 이미 해당 버전인 수집기에는 아무것도 전달되지 않습니다.", - "confirmRollbackNoStable": "안정 버전으로 즉시 롤백하는 롤아웃을 시작합니다.", + "confirmRollbackNoStable": "이 플릿에는 안정 버전이 없으므로 롤아웃이 종료되고, 다시 배포할 때까지 수집기들이 수집을 중단합니다.", "confirmSkip": "실패한 수집기 {count}개를 제외하고 계속합니다. 제외 표시되며 다음 롤아웃에 다시 포함됩니다. | 실패한 수집기 {count}개를 제외하고 계속합니다. 제외 표시되며 다음 롤아웃에 다시 포함됩니다.", "confirmed": "확인됨", "eventConverged": "{n}단계 수렴 완료", @@ -29479,6 +29509,7 @@ "phaseN": "{n}단계", "phaseTimedOut": "시간 초과", "phaseTimeoutNote": "{minutes}분 안에 확인도 거부도 하지 않는 단계가 있으면 롤아웃이 중단됩니다 (플릿 설정)", + "phaseTimeoutNoteSeconds": "{minutes}분 {seconds}초 이내에 확인도 거부도 하지 않는 단계는 롤아웃을 중단합니다(플릿 설정)", "phaseVerifying": "검증 중", "phases": "단계", "planEmpty": "온라인 상태인 컬렉터가 없어 하나가 연결될 때까지 롤아웃이 대기합니다", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "상속 ({value})", "offlineHeartbeats": "오프라인으로 간주하는 하트비트 누락 횟수", "offlineHeartbeatsHelp": "메시지 없이 이 횟수만큼 하트비트 간격이 지나면 수집기는 오프라인입니다", - "offlineRatio": "오프라인 비율 이벤트 (%)", - "offlineRatioHelp": "이 비율을 넘는 수집기가 오프라인이면 플릿 이벤트를 기록합니다", + "offlineRatio": "오프라인 비율 (%)", + "offlineRatioHelp": "수집기 중 이 비율을 초과하여 오프라인일 때 해당 단계를 중단합니다", "outOfRange": "{min}에서 {max} 사이의 숫자를 입력하세요", "phaseTimeout": "단계 제한 시간 (초)", "phaseTimeoutHelp": "이 시간 안에 확인도 거부도 하지 않는 롤아웃 단계는 중단됩니다", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "오류 {count}개 · 게시 불가 | 오류 {count}개 · 게시 불가", "saveNewFirst": "게시하기 전에 새 구성을 저장하세요", "saveDraft": "초안 저장", + "publishUnchanged": "최신 버전입니다. 새 버전을 게시하려면 편집하세요.", "publishVersion": "버전 게시", "modeDraft": "초안 편집 중", "modeRollingOut": "v{version} 롤아웃 중", diff --git a/web/src/locales/languages/nl-NL.json b/web/src/locales/languages/nl-NL.json index 68daf8b6ac..fd83219eab 100644 --- a/web/src/locales/languages/nl-NL.json +++ b/web/src/locales/languages/nl-NL.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Niet in je licentie", + "title": "{feature} is niet inbegrepen in je licentie", + "description": "Je beheerder kan het toevoegen door de licentie bij te werken, of neem contact op met sales voor een licentie die het bevat.", + "thisFeature": "Deze functie", + "contactSales": "Contact opnemen met sales", + "toastTitle": "Niet inbegrepen in je licentie", + "toastMessage": "Je licentie bevat niet: {features}. Vraag je beheerder de licentie bij te werken.", + "toastMessageGeneric": "Je licentie bevat deze functie niet. Vraag je beheerder de licentie bij te werken.", + "bannerMessage": "Deze functie is vergrendeld. Er is de functie {feature} in je licentie voor nodig.", + "bannerMessageGeneric": "Deze pagina vereist een functie die niet in je licentie zit.", + "headerLocked": "Vergrendeld: {feature} nodig" + }, "emptyState": { "illustrations": { "noHistoryYet": "Nog geen geschiedenis", @@ -3407,6 +3420,22 @@ "contact_name": "Naam van de contactpersoon", "contact_email": "E-mailadres voor contact", "environment_type": "Omgevingstype", + "features": "Functies", + "features_all_unlocked": "Je licentie ontgrendelt alle functies.", + "features_summary": "Je licentie ontgrendelt {ratio}. {free} gratis functie is altijd inbegrepen. | Je licentie ontgrendelt {ratio}. {free} gratis functies zijn altijd inbegrepen.", + "features_paid_ratio": "{unlocked} van {paid} betaalde functie | {unlocked} van {paid} betaalde functies", + "features_unlocked": "Ontgrendeld", + "features_missing": "Niet in je licentie", + "features_request_access": "Toegang aanvragen", + "features_search": "Zoek in {count} functie | Zoek in alle {count} functies", + "features_filter_all": "Alle", + "features_filter_free": "Gratis", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Geen functies gevonden voor je zoekopdracht", + "features_none": "Geen functies in deze groep", + "features_free_heading": "Gratis, inbegrepen bij elke licentie", + "features_new": "Nieuw na je licentie", + "features_filter_new": "Nieuw", "request_new_license": "Nieuwe licentie aanvragen", "add_new_license_key": "Nieuwe licentiecode toevoegen", "refresh_license_limits": "Licentielimieten vernieuwen", @@ -29304,7 +29333,7 @@ "remove": "Verwijderen", "removeManyTitle": "{count} collectors verwijderen?", "removeMessage": "Dit verwijdert alleen de rij. Een host waarop de collector nog draait, verschijnt bij de volgende heartbeat weer, dus verwijder hem daar eerst.", - "removeOnlineMessage": "Dit verwijdert alleen de rij. {count} van deze collectors is online en verschijnt bij de volgende heartbeat weer; verwijder hem eerst op de host. | Dit verwijdert alleen de rijen. {count} van deze collectors zijn online en verschijnen bij de volgende heartbeat weer; verwijder ze eerst op hun hosts.", + "removeOnlineMessage": "Hiermee wordt alleen de rij verwijderd. {count} van deze collectors is online en verschijnt weer bij de volgende heartbeat, tenzij het enrollment-token is opgebruikt: dan blijft hij verborgen en blijft hij gegevens versturen. Verwijder hem daarom eerst op zijn host. | Hiermee worden alleen de rijen verwijderd. {count} van deze collectors zijn online en verschijnen weer bij hun volgende heartbeat, tenzij hun enrollment-token is opgebruikt: dan blijven ze verborgen en blijven ze gegevens versturen. Verwijder ze daarom eerst op hun hosts.", "removeTitle": "{name} verwijderen?", "removedCount": "{count} collector verwijderd | {count} collectors verwijderd", "rename": "Naam wijzigen", @@ -29314,6 +29343,7 @@ "restartManyTitle": "{count} collectors herstarten?", "restartMessage": "Elke collector herstart bij zijn volgende bericht van de server. Het verzamelen van gegevens pauzeert kort op elke host.", "restartQueued": "Herstart aangevraagd voor {count} collector | Herstart aangevraagd voor {count} collectors", + "restartOffline": "Deze collector is offline. Herstart hem zodra hij weer online is.", "restartUnsupported": "Deze collector accepteert geen herstartopdrachten", "systemSections": "Door het systeem beheerde secties", "systemSectionsCaption": "OpAMP-extensie en servicetelemetrie, ingesteld door de supervisor en de server", @@ -29327,7 +29357,7 @@ "noVersion": "Nog geen", "members": "Collectors", "membersOnline": "{online} van {total} online", - "atDesired": "{count} van {total} op de gewenste versie", + "atDesired": "{count} van {total} toegewezen aan de gewenste versie", "changeVersion": "Implementeren", "deployVersion": "Een versie implementeren", "deletedFleet": "Verwijderde fleet", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Opent de editor voor {config}. Publiceer een gecorrigeerde versie en zet deze fleet daarop; deze uitrol wordt dan vervangen.", "confirmResume": "Dezelfde uitrol gaat verder vanaf fase {n}.", "confirmRollback": "Start direct een uitrol terug naar de stabiele versie, {config} v{version}. Collectors die er al op staan, ontvangen niets.", - "confirmRollbackNoStable": "Start direct een uitrol terug naar de stabiele versie.", + "confirmRollbackNoStable": "Deze fleet heeft geen stabiele versie, dus de uitrol eindigt en de collectors stoppen met verzamelen tot je opnieuw deployt.", "confirmSkip": "Sluit {count} falende collector uit en gaat verder. Deze wordt als uitgesloten gemarkeerd en bij de volgende uitrol opnieuw meegenomen. | Sluit {count} falende collectors uit en gaat verder. Ze worden als uitgesloten gemarkeerd en bij de volgende uitrol opnieuw meegenomen.", "confirmed": "Bevestigd", "eventConverged": "Fase {n} geconvergeerd", @@ -29479,6 +29509,7 @@ "phaseN": "Fase {n}", "phaseTimedOut": "Verlopen", "phaseTimeoutNote": "Een fase die binnen {minutes} min niet bevestigt of weigert, stopt de uitrol (fleet-instelling)", + "phaseTimeoutNoteSeconds": "Een fase die niet binnen {minutes} min {seconds} s bevestigt of afwijst, stopt de uitrol (fleetinstelling)", "phaseVerifying": "Verifiëren", "phases": "Fasen", "planEmpty": "Er is geen collector online, dus de uitrol wacht tot er één verbinding maakt", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Standaardwaarde ({value})", "offlineHeartbeats": "Offline na gemiste heartbeats", "offlineHeartbeatsHelp": "Een collector is offline na zoveel heartbeat-intervallen zonder bericht", - "offlineRatio": "Offline-aandeelgebeurtenis (%)", - "offlineRatioHelp": "Legt een fleet-gebeurtenis vast wanneer meer dan dit aandeel van de collectors offline is", + "offlineRatio": "Offline-ratio (%)", + "offlineRatioHelp": "Stopt de fase wanneer meer dan dit aandeel van de collectors offline is", "outOfRange": "Voer een getal van {min} tot {max} in", "phaseTimeout": "Fasetime-out (seconden)", "phaseTimeoutHelp": "Een uitrolfase die in deze tijd niet bevestigt of weigert, stopt", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} fout · publiceren geblokkeerd | {count} fouten · publiceren geblokkeerd", "saveNewFirst": "Sla de nieuwe configuratie op voordat je publiceert", "saveDraft": "Concept opslaan", + "publishUnchanged": "Dit is de nieuwste versie. Bewerk deze om een nieuwe te publiceren.", "publishVersion": "Versie publiceren", "modeDraft": "Concept bewerken", "modeRollingOut": "v{version} wordt uitgerold", diff --git a/web/src/locales/languages/pl-PL.json b/web/src/locales/languages/pl-PL.json index c96c866838..a982403469 100644 --- a/web/src/locales/languages/pl-PL.json +++ b/web/src/locales/languages/pl-PL.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Brak w Twojej licencji", + "title": "Funkcja {feature} nie jest objęta licencją", + "description": "Administrator może ją dodać, aktualizując licencję, lub możesz skontaktować się z działem sprzedaży, aby uzyskać licencję, która ją obejmuje.", + "thisFeature": "Ta funkcja", + "contactSales": "Skontaktuj się z działem sprzedaży", + "toastTitle": "Nieobjęte licencją", + "toastMessage": "Twoja licencja nie obejmuje: {features}. Poproś administratora o aktualizację licencji.", + "toastMessageGeneric": "Twoja licencja nie obejmuje tej funkcji. Poproś administratora o aktualizację licencji.", + "bannerMessage": "Ta funkcja jest zablokowana. Wymaga funkcji {feature} w Twojej licencji.", + "bannerMessageGeneric": "Ta strona wymaga funkcji, której nie ma w Twojej licencji.", + "headerLocked": "Zablokowane: wymaga {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "Brak historii", @@ -3407,6 +3420,22 @@ "contact_name": "Imię i nazwisko kontaktowe", "contact_email": "Adres e-mail kontaktowy", "environment_type": "Typ środowiska", + "features": "Funkcje", + "features_all_unlocked": "Twoja licencja odblokowuje wszystkie funkcje.", + "features_summary": "Twoja licencja odblokowuje {ratio}. Zawsze uwzględniana jest {free} darmowa funkcja. | Twoja licencja odblokowuje {ratio}. Zawsze uwzględniane są {free} darmowe funkcje.", + "features_paid_ratio": "{unlocked} z {paid} płatnej funkcji | {unlocked} z {paid} płatnych funkcji", + "features_unlocked": "Odblokowane", + "features_missing": "Brak w licencji", + "features_request_access": "Poproś o dostęp", + "features_search": "Przeszukaj {count} funkcję | Przeszukaj wszystkie {count} funkcje", + "features_filter_all": "Wszystkie", + "features_filter_free": "Darmowe", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Żadne funkcje nie pasują do wyszukiwania", + "features_none": "Brak funkcji w tej grupie", + "features_free_heading": "Darmowe, uwzględniane w każdej licencji", + "features_new": "Nowe po dacie licencji", + "features_filter_new": "Nowe", "request_new_license": "Poproś o nową licencję", "add_new_license_key": "Dodaj nowy klucz licencyjny", "refresh_license_limits": "Odśwież limity licencji", @@ -29304,7 +29333,7 @@ "remove": "Usuń", "removeManyTitle": "Usunąć kolektory ({count})?", "removeMessage": "Spowoduje to usunięcie tylko tego wiersza. Host, na którym nadal działa kolektor, pojawi się ponownie przy następnym heartbeacie, więc najpierw odinstaluj go na nim.", - "removeOnlineMessage": "Spowoduje to usunięcie tylko wiersza. {count} z tych kolektorów jest online i pojawi się ponownie przy następnym heartbeacie; najpierw odinstaluj go na jego hoście. | Spowoduje to usunięcie tylko wierszy. {count} z tych kolektorów jest online i pojawi się ponownie przy następnym heartbeacie; najpierw odinstaluj je na ich hostach.", + "removeOnlineMessage": "To usuwa tylko wiersz. {count} z tych kolektorów jest online i pojawi się ponownie przy następnym heartbeacie, chyba że jego token rejestracji został wykorzystany: wtedy pozostanie ukryty i będzie nadal wysyłać dane. Dlatego najpierw odinstaluj go na jego hoście. | To usuwa tylko wiersze. {count} z tych kolektorów jest online i pojawią się ponownie przy następnym heartbeacie, chyba że ich token rejestracji został wykorzystany: wtedy pozostaną ukryte i będą nadal wysyłać dane. Dlatego najpierw odinstaluj je na ich hostach.", "removeTitle": "Usunąć {name}?", "removedCount": "Usunięto kolektor: {count} | Usunięto kolektory: {count}", "rename": "Zmień nazwę", @@ -29314,6 +29343,7 @@ "restartManyTitle": "Uruchomić ponownie kolektory ({count})?", "restartMessage": "Każdy kolektor uruchomi się ponownie po następnej wiadomości z serwera. Zbieranie danych na każdym hoście na chwilę się wstrzyma.", "restartQueued": "Zażądano restartu kolektora: {count} | Zażądano restartu kolektorów: {count}", + "restartOffline": "Ten kolektor jest offline. Uruchom go ponownie, gdy znów będzie dostępny.", "restartUnsupported": "Ten kolektor nie przyjmuje poleceń restartu", "systemSections": "Sekcje zarządzane przez system", "systemSectionsCaption": "Rozszerzenie OpAMP i telemetria usługi, ustawiane przez supervisora i serwer", @@ -29327,7 +29357,7 @@ "noVersion": "Jeszcze brak", "members": "Kolektory", "membersOnline": "{online} z {total} online", - "atDesired": "{count} z {total} w wersji docelowej", + "atDesired": "{count} z {total} ma przypisaną żądaną wersję", "changeVersion": "Wdróż", "deployVersion": "Wdróż wersję", "deletedFleet": "Usunięta flota", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Otwiera edytor {config}. Opublikuj poprawioną wersję i ustaw ją dla tej floty; to wdrożenie zostanie wtedy zastąpione.", "confirmResume": "To samo wdrożenie jest kontynuowane od fazy {n}.", "confirmRollback": "Uruchamia natychmiastowe wdrożenie z powrotem do wersji stabilnej, {config} v{version}. Kolektory, które już ją mają, nic nie otrzymają.", - "confirmRollbackNoStable": "Uruchamia natychmiastowe wdrożenie z powrotem do wersji stabilnej.", + "confirmRollbackNoStable": "Ta flota nie ma stabilnej wersji, więc wdrożenie zostanie zakończone, a jej kolektory przestaną zbierać dane, dopóki nie wdrożysz ponownie.", "confirmSkip": "Wyklucza kolektor z błędem ({count}) i kontynuuje. Zostaje oznaczony jako wykluczony i ponownie uwzględniony w następnym wdrożeniu. | Wyklucza kolektory z błędami ({count}) i kontynuuje. Zostają oznaczone jako wykluczone i ponownie uwzględnione w następnym wdrożeniu.", "confirmed": "Potwierdzono", "eventConverged": "Faza {n} osiągnęła stan docelowy", @@ -29479,6 +29509,7 @@ "phaseN": "Faza {n}", "phaseTimedOut": "Przekroczono czas", "phaseTimeoutNote": "Faza, która nie potwierdzi ani nie odrzuci w ciągu {minutes} min, wstrzymuje wdrożenie (ustawienie floty)", + "phaseTimeoutNoteSeconds": "Faza, która nie zostanie potwierdzona ani odrzucona w ciągu {minutes} min {seconds} s, wstrzymuje wdrożenie (ustawienie floty)", "phaseVerifying": "Weryfikacja", "phases": "Fazy", "planEmpty": "Żaden kolektor nie jest online, więc wdrożenie poczeka, aż któryś się połączy", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Dziedzicz ({value})", "offlineHeartbeats": "Offline po pominiętych heartbeatach", "offlineHeartbeatsHelp": "Kolektor jest offline po tylu interwałach heartbeatu bez wiadomości", - "offlineRatio": "Zdarzenie odsetka offline (%)", - "offlineRatioHelp": "Zapisuje zdarzenie floty, gdy więcej niż ten odsetek kolektorów jest offline", + "offlineRatio": "Odsetek offline (%)", + "offlineRatioHelp": "Wstrzymuje fazę, gdy więcej niż ten odsetek jej kolektorów jest offline", "outOfRange": "Wpisz liczbę od {min} do {max}", "phaseTimeout": "Limit czasu fazy (sekundy)", "phaseTimeoutHelp": "Faza wdrożenia, która nie potwierdzi ani nie odrzuci w tym czasie, zostaje wstrzymana", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "Błąd: {count} · publikacja zablokowana | Błędy: {count} · publikacja zablokowana", "saveNewFirst": "Zapisz nową konfigurację przed publikacją", "saveDraft": "Zapisz wersję roboczą", + "publishUnchanged": "To jest najnowsza wersja. Edytuj ją, aby opublikować nową.", "publishVersion": "Opublikuj wersję", "modeDraft": "Edycja wersji roboczej", "modeRollingOut": "Wersja v{version} jest wdrażana", diff --git a/web/src/locales/languages/pt-PT.json b/web/src/locales/languages/pt-PT.json index d5e7038834..1291f4ce97 100644 --- a/web/src/locales/languages/pt-PT.json +++ b/web/src/locales/languages/pt-PT.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Não incluído na sua licença", + "title": "{feature} não está incluído na sua licença", + "description": "O seu administrador pode adicioná-lo atualizando a licença, ou contacte a equipa comercial para obter uma licença que o inclua.", + "thisFeature": "Esta funcionalidade", + "contactSales": "Contactar equipa comercial", + "toastTitle": "Não incluído na sua licença", + "toastMessage": "A sua licença não inclui: {features}. Peça ao seu administrador para atualizar a licença.", + "toastMessageGeneric": "A sua licença não inclui esta funcionalidade. Peça ao seu administrador para atualizar a licença.", + "bannerMessage": "Esta funcionalidade está bloqueada. Requer a funcionalidade {feature} na sua licença.", + "bannerMessageGeneric": "Esta página requer uma funcionalidade que não está na sua licença.", + "headerLocked": "Bloqueado: requer {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "Sem histórico ainda", @@ -3407,6 +3420,22 @@ "contact_name": "Nome do contacto", "contact_email": "E-mail de contacto", "environment_type": "Tipo de ambiente", + "features": "Funcionalidades", + "features_all_unlocked": "A sua licença desbloqueia todas as funcionalidades.", + "features_summary": "A sua licença desbloqueia {ratio}. {free} funcionalidade gratuita está sempre incluída. | A sua licença desbloqueia {ratio}. {free} funcionalidades gratuitas estão sempre incluídas.", + "features_paid_ratio": "{unlocked} de {paid} funcionalidade paga | {unlocked} de {paid} funcionalidades pagas", + "features_unlocked": "Desbloqueado", + "features_missing": "Não incluído na sua licença", + "features_request_access": "Pedir acesso", + "features_search": "Pesquisar {count} funcionalidade | Pesquisar todas as {count} funcionalidades", + "features_filter_all": "Todas", + "features_filter_free": "Gratuitas", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Nenhuma funcionalidade corresponde à sua pesquisa", + "features_none": "Nenhuma funcionalidade neste grupo", + "features_free_heading": "Gratuitas, incluídas em todas as licenças", + "features_new": "Novas depois da sua licença", + "features_filter_new": "Novas", "request_new_license": "Solicitar nova licença", "add_new_license_key": "Adicionar nova chave de licença", "refresh_license_limits": "Atualizar limites de licença", @@ -29304,7 +29333,7 @@ "remove": "Remover", "removeManyTitle": "Remover {count} coletores?", "removeMessage": "Isto remove apenas a linha. Um host que ainda execute o coletor volta a aparecer no próximo heartbeat, por isso desinstale-o primeiro nesse host.", - "removeOnlineMessage": "Isto remove apenas a linha. {count} destes coletores está online e volta a aparecer no próximo heartbeat; desinstale-o primeiro no respetivo host. | Isto remove apenas as linhas. {count} destes coletores estão online e voltam a aparecer no próximo heartbeat; desinstale-os primeiro nos respetivos hosts.", + "removeOnlineMessage": "Isto remove apenas a linha. {count} destes coletores está online e volta a aparecer no próximo heartbeat, a menos que o seu token de inscrição esteja esgotado: nesse caso, permanece oculto e continua a enviar dados. Por isso, desinstale-o primeiro no respetivo host. | Isto remove apenas as linhas. {count} destes coletores estão online e voltam a aparecer no próximo heartbeat, a menos que o respetivo token de inscrição esteja esgotado: nesse caso, permanecem ocultos e continuam a enviar dados. Por isso, desinstale-os primeiro nos respetivos hosts.", "removeTitle": "Remover {name}?", "removedCount": "{count} coletor removido | {count} coletores removidos", "rename": "Mudar o nome", @@ -29314,6 +29343,7 @@ "restartManyTitle": "Reiniciar {count} coletores?", "restartMessage": "Cada coletor reinicia na próxima mensagem do servidor. A recolha de dados pára brevemente em cada anfitrião.", "restartQueued": "Reinício solicitado para {count} coletor | Reinício solicitado para {count} coletores", + "restartOffline": "Este coletor está offline. Reinicie-o quando estiver novamente online.", "restartUnsupported": "Este coletor não aceita comandos de reinício", "systemSections": "Secções geridas pelo sistema", "systemSectionsCaption": "Extensão OpAMP e telemetria do serviço, definidas pelo supervisor e pelo servidor", @@ -29327,7 +29357,7 @@ "noVersion": "Ainda nenhuma", "members": "Coletores", "membersOnline": "{online} de {total} online", - "atDesired": "{count} de {total} na versão pretendida", + "atDesired": "{count} de {total} com a versão pretendida atribuída", "changeVersion": "Implementar", "deployVersion": "Implementar uma versão", "deletedFleet": "Frota eliminada", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Abre o editor de {config}. Publique uma versão corrigida e mude esta frota para ela; esta implementação fica então substituída.", "confirmResume": "A mesma implementação continua a partir da fase {n}.", "confirmRollback": "Inicia de imediato uma implementação de regresso à versão estável, {config} v{version}. Os coletores que já a têm não recebem nada.", - "confirmRollbackNoStable": "Inicia de imediato uma implementação de regresso à versão estável.", + "confirmRollbackNoStable": "Esta frota não tem uma versão estável, pelo que a implementação termina e os seus coletores deixam de recolher até voltar a implementar.", "confirmSkip": "Exclui {count} coletor com falhas e continua. Fica marcado como excluído e é incluído novamente na próxima implementação. | Exclui {count} coletores com falhas e continua. Ficam marcados como excluídos e são incluídos novamente na próxima implementação.", "confirmed": "Confirmado", "eventConverged": "Fase {n} convergiu", @@ -29479,6 +29509,7 @@ "phaseN": "Fase {n}", "phaseTimedOut": "Tempo limite excedido", "phaseTimeoutNote": "Uma fase que não confirma nem rejeita em {minutes} min interrompe a implementação (definição da frota)", + "phaseTimeoutNoteSeconds": "Uma fase que não confirme nem rejeite dentro de {minutes} min {seconds} s interrompe a implementação (definição da frota)", "phaseVerifying": "A verificar", "phases": "Fases", "planEmpty": "Nenhum coletor está online, pelo que a implementação aguarda até um se ligar", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Herdar ({value})", "offlineHeartbeats": "Offline após heartbeats em falta", "offlineHeartbeatsHelp": "Um coletor fica offline após este número de intervalos de heartbeat sem mensagem", - "offlineRatio": "Evento de proporção offline (%)", - "offlineRatioHelp": "Regista um evento da frota quando mais do que esta proporção de coletores está offline", + "offlineRatio": "Proporção offline (%)", + "offlineRatioHelp": "Interrompe a fase quando mais do que esta proporção dos seus coletores está offline", "outOfRange": "Introduza um número de {min} a {max}", "phaseTimeout": "Tempo limite da fase (segundos)", "phaseTimeoutHelp": "Uma fase da implementação que não confirma nem rejeita neste tempo é interrompida", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} erro · publicação bloqueada | {count} erros · publicação bloqueada", "saveNewFirst": "Guarde a nova configuração antes de publicar", "saveDraft": "Guardar rascunho", + "publishUnchanged": "Esta é a versão mais recente. Edite-a para publicar uma nova.", "publishVersion": "Publicar versão", "modeDraft": "A editar rascunho", "modeRollingOut": "v{version} em implementação", diff --git a/web/src/locales/languages/ru-RU.json b/web/src/locales/languages/ru-RU.json index 88dd7feeac..6c8de6a578 100644 --- a/web/src/locales/languages/ru-RU.json +++ b/web/src/locales/languages/ru-RU.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Не входит в вашу лицензию", + "title": "{feature} не входит в вашу лицензию", + "description": "Администратор может добавить её, обновив лицензию, или обратитесь в отдел продаж за лицензией, которая её включает.", + "thisFeature": "Эта функция", + "contactSales": "Связаться с отделом продаж", + "toastTitle": "Не входит в вашу лицензию", + "toastMessage": "Ваша лицензия не включает: {features}. Попросите администратора обновить лицензию.", + "toastMessageGeneric": "Ваша лицензия не включает эту функцию. Попросите администратора обновить лицензию.", + "bannerMessage": "Эта функция заблокирована. Для неё требуется функция {feature} в вашей лицензии.", + "bannerMessageGeneric": "Для этой страницы нужна функция, которой нет в вашей лицензии.", + "headerLocked": "Заблокировано: требуется {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "Истории пока нет", @@ -3407,6 +3420,22 @@ "contact_name": "Контактное лицо", "contact_email": "Контактный email", "environment_type": "Тип среды", + "features": "Функции", + "features_all_unlocked": "Ваша лицензия открывает все функции.", + "features_summary": "Ваша лицензия открывает {ratio}. {free} бесплатная функция всегда включена. | Ваша лицензия открывает {ratio}. {free} бесплатные функции всегда включены.", + "features_paid_ratio": "{unlocked} из {paid} платной функции | {unlocked} из {paid} платных функций", + "features_unlocked": "Доступно", + "features_missing": "Не входит в вашу лицензию", + "features_request_access": "Запросить доступ", + "features_search": "Поиск по {count} функции | Поиск по всем {count} функциям", + "features_filter_all": "Все", + "features_filter_free": "Бесплатные", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Нет функций, соответствующих вашему поиску", + "features_none": "В этой группе нет функций", + "features_free_heading": "Бесплатные функции входят в каждую лицензию", + "features_new": "Новые после вашей лицензии", + "features_filter_new": "Новые", "request_new_license": "Запросить новую лицензию", "add_new_license_key": "Добавить новый ключ лицензии", "refresh_license_limits": "Обновить лимиты лицензии", @@ -29304,7 +29333,7 @@ "remove": "Удалить", "removeManyTitle": "Удалить коллекторы ({count})?", "removeMessage": "Удаляется только строка. Хост, на котором всё ещё работает коллектор, появится снова при следующем heartbeat, поэтому сначала удалите коллектор на нём.", - "removeOnlineMessage": "Удаляются только строки. {count} из этих коллекторов в сети и появится снова при следующем heartbeat; сначала удалите его на его хосте. | Удаляются только строки. {count} из этих коллекторов в сети и появятся снова при следующем heartbeat; сначала удалите их на их хостах.", + "removeOnlineMessage": "Это удаляет только строку. {count} из этих коллекторов находится в сети и снова появится при следующем сигнале активности, если только его токен регистрации не исчерпан: тогда он останется скрытым и продолжит отправлять данные. Поэтому сначала удалите его на хосте. | Это удаляет только строки. {count} из этих коллекторов находятся в сети и снова появятся при следующем сигнале активности, если только их токены регистрации не исчерпаны: тогда они останутся скрытыми и продолжат отправлять данные. Поэтому сначала удалите их на хостах.", "removeTitle": "Удалить {name}?", "removedCount": "Удалён {count} коллектор | Удалено коллекторов: {count}", "rename": "Переименовать", @@ -29314,6 +29343,7 @@ "restartManyTitle": "Перезапустить коллекторы ({count})?", "restartMessage": "Каждый коллектор перезапустится при следующем сообщении от сервера. Сбор данных на каждом хосте ненадолго приостановится.", "restartQueued": "Запрошен перезапуск {count} коллектора | Запрошен перезапуск коллекторов: {count}", + "restartOffline": "Этот коллектор не в сети. Перезапустите его, когда он снова будет в сети.", "restartUnsupported": "Этот коллектор не принимает команды перезапуска", "systemSections": "Разделы, управляемые системой", "systemSectionsCaption": "Расширение OpAMP и телеметрия сервиса, задаются supervisor и сервером", @@ -29327,7 +29357,7 @@ "noVersion": "Пока нет", "members": "Коллекторы", "membersOnline": "{online} из {total} в сети", - "atDesired": "{count} из {total} на целевой версии", + "atDesired": "{count} из {total} с назначенной нужной версией", "changeVersion": "Развернуть", "deployVersion": "Развернуть версию", "deletedFleet": "Удалённый парк", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Открывает редактор {config}. Опубликуйте исправленную версию и переведите на неё этот парк; тогда это развертывание будет заменено.", "confirmResume": "То же развертывание продолжится с этапа {n}.", "confirmRollback": "Немедленно запускает откат на стабильную версию, {config} v{version}. Коллекторы, уже работающие на ней, ничего не получат.", - "confirmRollbackNoStable": "Немедленно запускает откат на стабильную версию.", + "confirmRollbackNoStable": "У этого парка нет стабильной версии, поэтому развёртывание завершится, а его коллекторы перестанут собирать данные, пока вы снова не выполните развёртывание.", "confirmSkip": "Исключает {count} сбойный коллектор и продолжает. Он помечается как исключённый и снова включается в следующее развертывание. | Исключает сбойные коллекторы ({count}) и продолжает. Они помечаются как исключённые и снова включаются в следующее развертывание.", "confirmed": "Подтверждено", "eventConverged": "Этап {n} завершён", @@ -29479,6 +29509,7 @@ "phaseN": "Этап {n}", "phaseTimedOut": "Время истекло", "phaseTimeoutNote": "Этап, который не подтверждается и не отклоняется за {minutes} мин, останавливает развертывание (настройка парка)", + "phaseTimeoutNoteSeconds": "Фаза, которая не подтвердит и не отклонит изменения в течение {minutes} мин {seconds} с, останавливает развёртывание (настройка парка)", "phaseVerifying": "Проверка", "phases": "Этапы", "planEmpty": "Ни один коллектор не в сети, поэтому развёртывание ждёт, пока не подключится хотя бы один.", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Наследовать ({value})", "offlineHeartbeats": "Не в сети после пропущенных heartbeat", "offlineHeartbeatsHelp": "Коллектор считается не в сети, если сообщений нет столько интервалов heartbeat", - "offlineRatio": "Событие доли «не в сети» (%)", - "offlineRatioHelp": "Записывает событие парка, когда не в сети более этой доли коллекторов", + "offlineRatio": "Доля не в сети (%)", + "offlineRatioHelp": "Останавливает фазу, когда доля её коллекторов не в сети превышает это значение", "outOfRange": "Введите число от {min} до {max}", "phaseTimeout": "Тайм-аут этапа (секунды)", "phaseTimeoutHelp": "Этап развертывания, который не подтверждается и не отклоняется за это время, останавливается", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} ошибка · публикация заблокирована | Ошибок: {count} · публикация заблокирована", "saveNewFirst": "Сохраните новую конфигурацию перед публикацией", "saveDraft": "Сохранить черновик", + "publishUnchanged": "Это последняя версия. Отредактируйте её, чтобы опубликовать новую.", "publishVersion": "Опубликовать версию", "modeDraft": "Редактирование черновика", "modeRollingOut": "v{version} развертывается", diff --git a/web/src/locales/languages/th-TH.json b/web/src/locales/languages/th-TH.json index 0c2e6b8492..bf55e202d8 100644 --- a/web/src/locales/languages/th-TH.json +++ b/web/src/locales/languages/th-TH.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "ไม่อยู่ในไลเซนส์ของคุณ", + "title": "{feature} ไม่รวมอยู่ในไลเซนส์ของคุณ", + "description": "ผู้ดูแลระบบของคุณสามารถเพิ่มได้โดยอัปเดตไลเซนส์ หรือติดต่อฝ่ายขายเพื่อรับไลเซนส์ที่รวมฟีเจอร์นี้", + "thisFeature": "ฟีเจอร์นี้", + "contactSales": "ติดต่อฝ่ายขาย", + "toastTitle": "ไม่รวมอยู่ในไลเซนส์ของคุณ", + "toastMessage": "ไลเซนส์ของคุณไม่รวมถึง: {features} โปรดแจ้งผู้ดูแลระบบของคุณให้อัปเดตไลเซนส์", + "toastMessageGeneric": "ไลเซนส์ของคุณไม่รวมฟีเจอร์นี้ โปรดแจ้งผู้ดูแลระบบของคุณให้อัปเดตไลเซนส์", + "bannerMessage": "ฟีเจอร์นี้ถูกล็อก ต้องมีฟีเจอร์ {feature} ในไลเซนส์ของคุณ", + "bannerMessageGeneric": "หน้านี้ต้องใช้ฟีเจอร์ที่ไม่อยู่ในไลเซนส์ของคุณ", + "headerLocked": "ล็อกอยู่: ต้องมี {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "No history yet", @@ -3407,6 +3420,22 @@ "contact_name": "Contact Name", "contact_email": "Contact Email", "environment_type": "Environment Type", + "features": "ฟีเจอร์", + "features_all_unlocked": "ไลเซนส์ของคุณปลดล็อกฟีเจอร์ทั้งหมด", + "features_summary": "ไลเซนส์ของคุณปลดล็อก {ratio} ฟีเจอร์ฟรี {free} รายการจะรวมอยู่ด้วยเสมอ | ไลเซนส์ของคุณปลดล็อก {ratio} ฟีเจอร์ฟรี {free} รายการจะรวมอยู่ด้วยเสมอ", + "features_paid_ratio": "{unlocked} จาก {paid} ฟีเจอร์แบบชำระเงิน | {unlocked} จาก {paid} ฟีเจอร์แบบชำระเงิน", + "features_unlocked": "ปลดล็อกแล้ว", + "features_missing": "ไม่อยู่ในไลเซนส์ของคุณ", + "features_request_access": "ขอสิทธิ์เข้าถึง", + "features_search": "ค้นหา {count} ฟีเจอร์ | ค้นหาฟีเจอร์ทั้งหมด {count} รายการ", + "features_filter_all": "ทั้งหมด", + "features_filter_free": "ฟรี", + "features_group_heading": "{heading} · {count}", + "features_no_match": "ไม่มีฟีเจอร์ที่ตรงกับการค้นหาของคุณ", + "features_none": "ไม่มีฟีเจอร์ในกลุ่มนี้", + "features_free_heading": "ฟรี รวมอยู่ในทุกไลเซนส์", + "features_new": "ใหม่หลังจากไลเซนส์ของคุณ", + "features_filter_new": "ใหม่", "request_new_license": "Request new License", "add_new_license_key": "Add New License Key", "refresh_license_limits": "Refresh License Limits", @@ -29302,7 +29331,7 @@ "remove": "Remove", "removeManyTitle": "Remove {count} collectors?", "removeMessage": "This removes the row only. A host that still runs the collector reappears on its next heartbeat, so uninstall it there first.", - "removeOnlineMessage": "This removes the row only. {count} of these collectors is online and reappears on its next heartbeat; uninstall it on its host first. | This removes the rows only. {count} of these collectors are online and reappear on their next heartbeat; uninstall them on their hosts first.", + "removeOnlineMessage": "การดำเนินการนี้จะลบเฉพาะแถวเท่านั้น {count} ของคอลเลกเตอร์เหล่านี้อยู่ในสถานะออนไลน์และจะปรากฏอีกครั้งในสัญญาณ heartbeat ครั้งถัดไป เว้นแต่โทเค็นการลงทะเบียนของคอลเลกเตอร์นั้นจะถูกใช้จนหมด: จากนั้นคอลเลกเตอร์จะยังคงซ่อนอยู่และส่งข้อมูลต่อไป ดังนั้นควรถอนการติดตั้งบนโฮสต์ของคอลเลกเตอร์นั้นก่อน | การดำเนินการนี้จะลบเฉพาะแถวเท่านั้น {count} ของคอลเลกเตอร์เหล่านี้อยู่ในสถานะออนไลน์และจะปรากฏอีกครั้งในสัญญาณ heartbeat ครั้งถัดไป เว้นแต่โทเค็นการลงทะเบียนของคอลเลกเตอร์เหล่านี้จะถูกใช้จนหมด: จากนั้นคอลเลกเตอร์เหล่านี้จะยังคงซ่อนอยู่และส่งข้อมูลต่อไป ดังนั้นควรถอนการติดตั้งบนโฮสต์ของคอลเลกเตอร์เหล่านี้ก่อน", "removeTitle": "Remove {name}?", "removedCount": "Removed {count} collector | Removed {count} collectors", "rename": "Rename", @@ -29312,6 +29341,7 @@ "restartManyTitle": "Restart {count} collectors?", "restartMessage": "Each collector restarts on its next message from the server. Data collection pauses briefly on each host.", "restartQueued": "Restart requested for {count} collector | Restart requested for {count} collectors", + "restartOffline": "คอลเลกเตอร์นี้อยู่ในสถานะออฟไลน์ รีสตาร์ตเมื่อกลับมาออนไลน์", "restartUnsupported": "This collector does not accept restart commands", "systemSections": "System-managed sections", "systemSectionsCaption": "OpAMP extension and service telemetry, set by the supervisor and the server", @@ -29325,7 +29355,7 @@ "noVersion": "None yet", "members": "Collectors", "membersOnline": "{online} of {total} online", - "atDesired": "{count} of {total} at the desired version", + "atDesired": "{count} จาก {total} ถูกกำหนดเป็นเวอร์ชันที่ต้องการ", "changeVersion": "Deploy", "deployVersion": "Deploy a version", "deletedFleet": "Deleted fleet", @@ -29440,7 +29470,7 @@ "confirmFixForward": "Opens the {config} editor. Publish a fixed version and change this fleet to it; this rollout is then superseded.", "confirmResume": "The same rollout continues from phase {n}.", "confirmRollback": "Starts an immediate rollout back to the stable version, {config} v{version}. Collectors already on it receive nothing.", - "confirmRollbackNoStable": "Starts an immediate rollout back to the stable version.", + "confirmRollbackNoStable": "กลุ่มเครื่องนี้ไม่มีเวอร์ชันเสถียร ดังนั้นการทยอยปรับใช้จะสิ้นสุดลง และคอลเลกเตอร์ของกลุ่มนี้จะหยุดเก็บข้อมูลจนกว่าคุณจะดีพลอยอีกครั้ง", "confirmSkip": "Excludes {count} failing collector and continues. It is marked excluded and included again in the next rollout. | Excludes {count} failing collectors and continues. They are marked excluded and included again in the next rollout.", "confirmed": "Confirmed", "eventConverged": "Phase {n} converged", @@ -29477,6 +29507,7 @@ "phaseN": "Phase {n}", "phaseTimedOut": "Timed out", "phaseTimeoutNote": "A phase that neither confirms nor rejects within {minutes} min halts the rollout (fleet setting)", + "phaseTimeoutNoteSeconds": "เฟสที่ไม่ยืนยันหรือปฏิเสธภายใน {minutes} นาที {seconds} วินาที จะหยุดการทยอยปรับใช้ (การตั้งค่ากลุ่มเครื่อง)", "phaseVerifying": "Verifying", "phases": "Phases", "planEmpty": "ไม่มีคอลเลกเตอร์ออนไลน์ ดังนั้นการทยอยติดตั้งจะรอจนกว่าจะมีตัวหนึ่งเชื่อมต่อ", @@ -29617,8 +29648,8 @@ "inheritPlaceholder": "Inherit ({value})", "offlineHeartbeats": "Offline after missed heartbeats", "offlineHeartbeatsHelp": "A collector is offline after this many heartbeat intervals without a message", - "offlineRatio": "Offline-ratio event (%)", - "offlineRatioHelp": "Records a fleet event when more than this share of collectors is offline", + "offlineRatio": "อัตราส่วนออฟไลน์ (%)", + "offlineRatioHelp": "จะหยุดเฟสเมื่อมีคอลเลกเตอร์ออฟไลน์เกินสัดส่วนนี้", "outOfRange": "Enter a number from {min} to {max}", "phaseTimeout": "Phase timeout (seconds)", "phaseTimeoutHelp": "A rollout phase that neither confirms nor rejects in this time halts", @@ -29726,6 +29757,7 @@ "publishBlockedChip": "{count} error · publish blocked | {count} errors · publish blocked", "saveNewFirst": "Save the new configuration before publishing", "saveDraft": "Save draft", + "publishUnchanged": "นี่คือเวอร์ชันล่าสุด แก้ไขเวอร์ชันนี้เพื่อเผยแพร่เวอร์ชันใหม่", "publishVersion": "Publish version", "modeDraft": "Editing draft", "modeRollingOut": "v{version} rolling out", diff --git a/web/src/locales/languages/tr-TR.json b/web/src/locales/languages/tr-TR.json index 1750a328f6..a87b22418d 100644 --- a/web/src/locales/languages/tr-TR.json +++ b/web/src/locales/languages/tr-TR.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Lisansınızda yok", + "title": "{feature} lisansınıza dahil değil", + "description": "Yöneticiniz lisansı güncelleyerek bunu ekleyebilir; bunu içeren bir lisans almak için satış ekibiyle iletişime geçin.", + "thisFeature": "Bu özellik", + "contactSales": "Satış ekibiyle iletişime geç", + "toastTitle": "Lisansınıza dahil değil", + "toastMessage": "Lisansınıza şunlar dahil değil: {features}. Lisansı güncellemesi için yöneticinize başvurun.", + "toastMessageGeneric": "Lisansınıza bu özellik dahil değil. Lisansı güncellemesi için yöneticinize başvurun.", + "bannerMessage": "Bu özellik kilitli. Lisansınızda {feature} özelliği gerekiyor.", + "bannerMessageGeneric": "Bu sayfa, lisansınızda olmayan bir özellik gerektiriyor.", + "headerLocked": "Kilitli: {feature} gerekiyor" + }, "emptyState": { "illustrations": { "noHistoryYet": "Henüz geçmiş yok", @@ -3407,6 +3420,22 @@ "contact_name": "İletişim Adı", "contact_email": "İletişim E-posta", "environment_type": "Ortam Türü", + "features": "Özellikler", + "features_all_unlocked": "Lisansınız tüm özelliklerin kilidini açar.", + "features_summary": "Lisansınızla {ratio} kullanılabilir. {free} ücretsiz özellik her zaman dahildir. | Lisansınızla {ratio} kullanılabilir. {free} ücretsiz özellik her zaman dahildir.", + "features_paid_ratio": "{unlocked} / {paid} ücretli özellik | {unlocked} / {paid} ücretli özellik", + "features_unlocked": "Kilidi açık", + "features_missing": "Lisansınızda yok", + "features_request_access": "Erişim Talep Et", + "features_search": "{count} özellikte ara | Tüm {count} özellikte ara", + "features_filter_all": "Tümü", + "features_filter_free": "Ücretsiz", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Aramanızla eşleşen özellik yok", + "features_none": "Bu grupta özellik yok", + "features_free_heading": "Ücretsiz, her lisansa dahil", + "features_new": "Lisansınızdan sonra eklenenler", + "features_filter_new": "Yeni", "request_new_license": "Yeni Lisans isteyin", "add_new_license_key": "Yeni Lisans Anahtarı Ekle", "refresh_license_limits": "Lisans Sınırlarını Yenile", @@ -29304,7 +29333,7 @@ "remove": "Kaldır", "removeManyTitle": "{count} toplayıcı kaldırılsın mı?", "removeMessage": "Bu yalnızca satırı kaldırır. Toplayıcıyı hâlâ çalıştıran bir ana bilgisayar, bir sonraki kalp atışında yeniden görünür; bu yüzden önce orada kaldırın.", - "removeOnlineMessage": "Bu yalnızca satırı kaldırır. Bu toplayıcılardan {count} tanesi çevrimiçi ve bir sonraki kalp atışında yeniden görünür; önce ana bilgisayarında kaldırın. | Bu yalnızca satırları kaldırır. Bu toplayıcılardan {count} tanesi çevrimiçi ve bir sonraki kalp atışında yeniden görünür; önce ana bilgisayarlarında kaldırın.", + "removeOnlineMessage": "Bu yalnızca satırı kaldırır. Bu toplayıcılardan {count} tanesi çevrimiçi ve kayıt token'ı tükenmemişse bir sonraki kalp atışında yeniden görünür; tükenmişse gizli kalır ve veri göndermeye devam eder. Bu yüzden önce ana bilgisayarında kaldırın. | Bu yalnızca satırları kaldırır. Bu toplayıcılardan {count} tanesi çevrimiçi ve kayıt token'ları tükenmemişse bir sonraki kalp atışlarında yeniden görünürler; tükenmişse gizli kalırlar ve veri göndermeye devam ederler. Bu yüzden önce ana bilgisayarlarında kaldırın.", "removeTitle": "{name} kaldırılsın mı?", "removedCount": "{count} toplayıcı kaldırıldı | {count} toplayıcı kaldırıldı", "rename": "Yeniden adlandır", @@ -29314,6 +29343,7 @@ "restartManyTitle": "{count} toplayıcı yeniden başlatılsın mı?", "restartMessage": "Her toplayıcı, sunucudan gelen bir sonraki mesajda yeniden başlar. Veri toplama her ana bilgisayarda kısa süre duraklar.", "restartQueued": "{count} toplayıcı için yeniden başlatma istendi | {count} toplayıcı için yeniden başlatma istendi", + "restartOffline": "Bu toplayıcı çevrimdışı. Geri geldiğinde yeniden başlatın.", "restartUnsupported": "Bu toplayıcı yeniden başlatma komutlarını kabul etmiyor", "systemSections": "Sistem tarafından yönetilen bölümler", "systemSectionsCaption": "OpAMP uzantısı ve hizmet telemetrisi; supervisor ve sunucu tarafından ayarlanır", @@ -29327,7 +29357,7 @@ "noVersion": "Henüz yok", "members": "Toplayıcılar", "membersOnline": "{total} toplayıcıdan {online} tanesi çevrimiçi", - "atDesired": "{total} toplayıcıdan {count} tanesi hedeflenen sürümde", + "atDesired": "{total} öğeden {count} tanesine istenen sürüm atandı", "changeVersion": "Dağıt", "deployVersion": "Sürüm dağıt", "deletedFleet": "Silinen filo", @@ -29442,7 +29472,7 @@ "confirmFixForward": "{config} düzenleyicisini açar. Düzeltilmiş bir sürüm yayınlayın ve bu filoyu ona geçirin; bu dağıtımın yerini o alır.", "confirmResume": "Aynı dağıtım {n}. aşamadan devam eder.", "confirmRollback": "Kararlı sürüme, {config} v{version}, hemen geri dönen bir dağıtım başlatır. Zaten bu sürümde olan toplayıcılara hiçbir şey gönderilmez.", - "confirmRollbackNoStable": "Kararlı sürüme hemen geri dönen bir dağıtım başlatır.", + "confirmRollbackNoStable": "Bu filonun kararlı bir sürümü yok; bu nedenle dağıtım sona erer ve siz yeniden dağıtım yapana kadar toplayıcılarının veri toplamasını durdurur.", "confirmSkip": "Başarısız olan {count} toplayıcıyı hariç tutar ve devam eder. Hariç tutuldu olarak işaretlenir ve bir sonraki dağıtıma yeniden dahil edilir. | Başarısız olan {count} toplayıcıyı hariç tutar ve devam eder. Hariç tutuldu olarak işaretlenirler ve bir sonraki dağıtıma yeniden dahil edilirler.", "confirmed": "Onaylandı", "eventConverged": "{n}. aşama yakınsadı", @@ -29479,6 +29509,7 @@ "phaseN": "{n}. aşama", "phaseTimedOut": "Zaman aşımı", "phaseTimeoutNote": "{minutes} dk içinde ne onaylanan ne de reddedilen bir aşama dağıtımı durdurur (filo ayarı)", + "phaseTimeoutNoteSeconds": "Bir aşama {minutes} dk {seconds} sn içinde onaylanmaz veya reddedilmezse dağıtımı durdurur (filo ayarı)", "phaseVerifying": "Doğrulanıyor", "phases": "Aşamalar", "planEmpty": "Hiçbir toplayıcı çevrimiçi değil, bu nedenle dağıtım bir toplayıcı bağlanana kadar bekler", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Devral ({value})", "offlineHeartbeats": "Kaçırılan kalp atışından sonra çevrimdışı", "offlineHeartbeatsHelp": "Bir toplayıcı, bu kadar kalp atışı aralığı boyunca mesaj göndermezse çevrimdışı sayılır", - "offlineRatio": "Çevrimdışı oranı olayı (%)", - "offlineRatioHelp": "Toplayıcıların bu orandan fazlası çevrimdışı olduğunda bir filo olayı kaydeder", + "offlineRatio": "Çevrimdışı oranı (%)", + "offlineRatioHelp": "Toplayıcılarının bu orandan daha fazlası çevrimdışı olduğunda aşamayı durdurur", "outOfRange": "{min} ile {max} arasında bir sayı girin", "phaseTimeout": "Aşama zaman aşımı (saniye)", "phaseTimeoutHelp": "Bu süre içinde ne onaylanan ne de reddedilen bir dağıtım aşaması durdurulur", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} hata · yayınlama engellendi | {count} hata · yayınlama engellendi", "saveNewFirst": "Yayınlamadan önce yeni yapılandırmayı kaydedin", "saveDraft": "Taslağı kaydet", + "publishUnchanged": "Bu, en son sürümdür. Yeni bir sürüm yayımlamak için düzenleyin.", "publishVersion": "Sürümü yayınla", "modeDraft": "Taslak düzenleniyor", "modeRollingOut": "v{version} dağıtılıyor", diff --git a/web/src/locales/languages/vi-VN.json b/web/src/locales/languages/vi-VN.json index 8533eab235..7010222c2d 100644 --- a/web/src/locales/languages/vi-VN.json +++ b/web/src/locales/languages/vi-VN.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "Không có trong giấy phép của bạn", + "title": "{feature} không được bao gồm trong giấy phép của bạn", + "description": "Quản trị viên của bạn có thể thêm tính năng này bằng cách cập nhật giấy phép, hoặc liên hệ bộ phận kinh doanh để nhận giấy phép có bao gồm tính năng này.", + "thisFeature": "Tính năng này", + "contactSales": "Liên hệ kinh doanh", + "toastTitle": "Không có trong giấy phép của bạn", + "toastMessage": "Giấy phép của bạn không bao gồm: {features}. Hãy yêu cầu quản trị viên cập nhật giấy phép.", + "toastMessageGeneric": "Giấy phép của bạn không bao gồm tính năng này. Hãy yêu cầu quản trị viên cập nhật giấy phép.", + "bannerMessage": "Tính năng này đã bị khóa. Cần có tính năng {feature} trong giấy phép của bạn.", + "bannerMessageGeneric": "Trang này cần một tính năng không có trong giấy phép của bạn.", + "headerLocked": "Đã khóa: cần {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "Chưa có lịch sử", @@ -3407,6 +3420,22 @@ "contact_name": "Tên liên hệ", "contact_email": "Email liên hệ", "environment_type": "Loại môi trường", + "features": "Tính năng", + "features_all_unlocked": "Giấy phép của bạn mở khóa tất cả tính năng.", + "features_summary": "Giấy phép của bạn mở khóa {ratio}. {free} tính năng miễn phí luôn được bao gồm. | Giấy phép của bạn mở khóa {ratio}. {free} tính năng miễn phí luôn được bao gồm.", + "features_paid_ratio": "{unlocked} trên {paid} tính năng trả phí | {unlocked} trên {paid} tính năng trả phí", + "features_unlocked": "Đã mở khóa", + "features_missing": "Không có trong giấy phép của bạn", + "features_request_access": "Yêu cầu quyền truy cập", + "features_search": "Tìm kiếm {count} tính năng | Tìm kiếm tất cả {count} tính năng", + "features_filter_all": "Tất cả", + "features_filter_free": "Miễn phí", + "features_group_heading": "{heading} · {count}", + "features_no_match": "Không có tính năng nào khớp với tìm kiếm của bạn", + "features_none": "Không có tính năng trong nhóm này", + "features_free_heading": "Miễn phí, có trong mọi giấy phép", + "features_new": "Mới sau giấy phép của bạn", + "features_filter_new": "Mới", "request_new_license": "Yêu cầu giấy phép mới", "add_new_license_key": "Thêm khóa giấy phép mới", "refresh_license_limits": "Làm mới giới hạn giấy phép", @@ -29304,7 +29333,7 @@ "remove": "Xóa", "removeManyTitle": "Xóa {count} collector?", "removeMessage": "Thao tác này chỉ xóa dòng. Máy chủ vẫn đang chạy collector sẽ xuất hiện lại ở lần gửi tín hiệu nhịp tim tiếp theo, vì vậy hãy gỡ cài đặt trên máy chủ đó trước.", - "removeOnlineMessage": "Thao tác này chỉ xóa dòng. {count} trong số các collector này đang trực tuyến và sẽ xuất hiện lại ở lần gửi tín hiệu nhịp tim tiếp theo; hãy gỡ cài đặt trên máy chủ của nó trước. | Thao tác này chỉ xóa các dòng. {count} trong số các collector này đang trực tuyến và sẽ xuất hiện lại ở lần gửi tín hiệu nhịp tim tiếp theo; hãy gỡ cài đặt trên các máy chủ của chúng trước.", + "removeOnlineMessage": "Thao tác này chỉ xóa hàng. {count} trong số các collector này đang trực tuyến và sẽ xuất hiện lại ở heartbeat tiếp theo, trừ khi token đăng ký của nó đã được dùng hết: khi đó nó sẽ vẫn bị ẩn và tiếp tục gửi dữ liệu. Vì vậy, hãy gỡ cài đặt nó trên máy chủ của nó trước. | Thao tác này chỉ xóa các hàng. {count} trong số các collector này đang trực tuyến và sẽ xuất hiện lại ở heartbeat tiếp theo, trừ khi token đăng ký của chúng đã được dùng hết: khi đó chúng sẽ vẫn bị ẩn và tiếp tục gửi dữ liệu. Vì vậy, hãy gỡ cài đặt chúng trên máy chủ của chúng trước.", "removeTitle": "Xóa {name}?", "removedCount": "Đã xóa {count} collector | Đã xóa {count} collector", "rename": "Đổi tên", @@ -29314,6 +29343,7 @@ "restartManyTitle": "Khởi động lại {count} collector?", "restartMessage": "Mỗi collector khởi động lại ở thông điệp kế tiếp từ máy chủ. Việc thu thập dữ liệu tạm dừng ngắn trên mỗi máy chủ.", "restartQueued": "Đã yêu cầu khởi động lại {count} collector | Đã yêu cầu khởi động lại {count} collector", + "restartOffline": "Collector này đang ngoại tuyến. Hãy khởi động lại khi nó trực tuyến trở lại.", "restartUnsupported": "Collector này không chấp nhận lệnh khởi động lại", "systemSections": "Phần do hệ thống quản lý", "systemSectionsCaption": "Tiện ích mở rộng OpAMP và dữ liệu đo từ xa của dịch vụ, do supervisor và máy chủ thiết lập", @@ -29327,7 +29357,7 @@ "noVersion": "Chưa có", "members": "Collector", "membersOnline": "{online} trên {total} trực tuyến", - "atDesired": "{count} trên {total} ở phiên bản mong muốn", + "atDesired": "{count} trên {total} đã được gán phiên bản mong muốn", "changeVersion": "Triển khai", "deployVersion": "Triển khai một phiên bản", "deletedFleet": "Fleet đã xóa", @@ -29442,7 +29472,7 @@ "confirmFixForward": "Mở trình chỉnh sửa {config}. Hãy phát hành một phiên bản đã sửa và đổi fleet này sang phiên bản đó; đợt triển khai này khi đó sẽ bị thay thế.", "confirmResume": "Cùng đợt triển khai này tiếp tục từ giai đoạn {n}.", "confirmRollback": "Bắt đầu ngay một đợt triển khai quay lui về phiên bản ổn định, {config} v{version}. Các collector đã ở phiên bản đó sẽ không nhận gì.", - "confirmRollbackNoStable": "Bắt đầu ngay một đợt triển khai quay lui về phiên bản ổn định.", + "confirmRollbackNoStable": "Fleet này không có phiên bản ổn định, vì vậy quá trình triển khai sẽ kết thúc và các collector của fleet sẽ ngừng thu thập cho đến khi bạn triển khai lại.", "confirmSkip": "Loại trừ {count} collector bị lỗi và tiếp tục. Nó được đánh dấu là bị loại trừ và được đưa vào lại ở đợt triển khai kế tiếp. | Loại trừ {count} collector bị lỗi và tiếp tục. Chúng được đánh dấu là bị loại trừ và được đưa vào lại ở đợt triển khai kế tiếp.", "confirmed": "Đã xác nhận", "eventConverged": "Giai đoạn {n} đã hội tụ", @@ -29479,6 +29509,7 @@ "phaseN": "Giai đoạn {n}", "phaseTimedOut": "Hết thời gian chờ", "phaseTimeoutNote": "Giai đoạn không xác nhận cũng không từ chối trong vòng {minutes} phút sẽ làm đợt triển khai dừng (cài đặt fleet)", + "phaseTimeoutNoteSeconds": "Một giai đoạn không xác nhận hay từ chối trong vòng {minutes} phút {seconds} giây sẽ dừng đợt triển khai (cài đặt fleet)", "phaseVerifying": "Đang xác minh", "phases": "Các giai đoạn", "planEmpty": "Không có collector nào trực tuyến, nên đợt triển khai chờ đến khi có một collector kết nối", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "Kế thừa ({value})", "offlineHeartbeats": "Ngoại tuyến sau số heartbeat bị lỡ", "offlineHeartbeatsHelp": "Collector bị coi là ngoại tuyến sau chừng này chu kỳ heartbeat không có thông điệp", - "offlineRatio": "Sự kiện tỷ lệ ngoại tuyến (%)", - "offlineRatioHelp": "Ghi lại một sự kiện fleet khi hơn tỷ lệ này số collector ngoại tuyến", + "offlineRatio": "Tỷ lệ ngoại tuyến (%)", + "offlineRatioHelp": "Tạm dừng giai đoạn khi tỷ lệ collector của giai đoạn bị ngoại tuyến vượt quá mức này", "outOfRange": "Nhập một số từ {min} đến {max}", "phaseTimeout": "Thời gian chờ giai đoạn (giây)", "phaseTimeoutHelp": "Giai đoạn triển khai không xác nhận cũng không từ chối trong thời gian này sẽ dừng", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} lỗi · không thể phát hành | {count} lỗi · không thể phát hành", "saveNewFirst": "Lưu cấu hình mới trước khi phát hành", "saveDraft": "Lưu bản nháp", + "publishUnchanged": "Đây là phiên bản mới nhất. Hãy chỉnh sửa để xuất bản phiên bản mới.", "publishVersion": "Phát hành phiên bản", "modeDraft": "Đang chỉnh sửa bản nháp", "modeRollingOut": "v{version} đang được triển khai", diff --git a/web/src/locales/languages/zh-CN.json b/web/src/locales/languages/zh-CN.json index 91a48a417d..0c7fa018e4 100644 --- a/web/src/locales/languages/zh-CN.json +++ b/web/src/locales/languages/zh-CN.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "不在您的许可证中", + "title": "{feature} 未包含在您的许可证中", + "description": "您的管理员可以通过更新许可证来添加它,或联系销售获取包含该功能的许可证。", + "thisFeature": "此功能", + "contactSales": "联系销售", + "toastTitle": "未包含在您的许可证中", + "toastMessage": "您的许可证不包含:{features}。请让管理员更新许可证。", + "toastMessageGeneric": "您的许可证不包含此功能。请让管理员更新许可证。", + "bannerMessage": "此功能已锁定。需要您的许可证中包含 {feature} 功能。", + "bannerMessageGeneric": "此页面需要一项不在您许可证中的功能。", + "headerLocked": "已锁定:需要 {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "暂无历史记录", @@ -3407,6 +3420,22 @@ "contact_name": "联系人姓名", "contact_email": "联系人邮箱", "environment_type": "环境类型", + "features": "功能", + "features_all_unlocked": "您的许可证已解锁所有功能。", + "features_summary": "您的许可证解锁了 {ratio}。{free} 个免费功能始终包含在内。 | 您的许可证解锁了 {ratio}。{free} 个免费功能始终包含在内。", + "features_paid_ratio": "{paid} 个付费功能中的 {unlocked} 个 | {paid} 个付费功能中的 {unlocked} 个", + "features_unlocked": "已解锁", + "features_missing": "不在您的许可证中", + "features_request_access": "申请访问权限", + "features_search": "搜索 {count} 个功能 | 搜索全部 {count} 个功能", + "features_filter_all": "全部", + "features_filter_free": "免费", + "features_group_heading": "{heading} · {count}", + "features_no_match": "没有符合搜索条件的功能", + "features_none": "此分组中没有功能", + "features_free_heading": "免费,每个许可证均包含", + "features_new": "许可证之后新增的功能", + "features_filter_new": "新增", "request_new_license": "申请新许可证", "add_new_license_key": "添加新的许可证密钥", "refresh_license_limits": "刷新许可证限制", @@ -29304,7 +29333,7 @@ "remove": "移除", "removeManyTitle": "移除 {count} 个 Collector?", "removeMessage": "此操作仅移除对应行。仍在运行采集器的主机会在下次心跳时重新出现,因此请先在该主机上卸载采集器。", - "removeOnlineMessage": "此操作仅移除对应行。这些采集器中有 {count} 个在线,并会在下次心跳时重新出现;请先在其主机上卸载。 | 此操作仅移除对应行。这些采集器中有 {count} 个在线,并会在下次心跳时重新出现;请先在其主机上卸载。", + "removeOnlineMessage": "这只会移除对应行。这些采集器中有 {count} 个处于在线状态,并会在下次心跳时重新出现;如果其注册令牌已用完,对应采集器就会保持隐藏并继续发送数据。因此请先在其主机上卸载对应采集器。 | 这只会移除对应行。这些采集器中有 {count} 个处于在线状态,并会在下次心跳时重新出现;如果其注册令牌已用完,对应采集器就会保持隐藏并继续发送数据。因此请先在其主机上卸载对应采集器。", "removeTitle": "移除 {name}?", "removedCount": "已移除 {count} 个 Collector | 已移除 {count} 个 Collector", "rename": "重命名", @@ -29314,6 +29343,7 @@ "restartManyTitle": "重启 {count} 个 Collector?", "restartMessage": "每个 Collector 将在收到服务器的下一条消息时重启。每台主机上的数据采集会短暂暂停。", "restartQueued": "已请求重启 {count} 个 Collector | 已请求重启 {count} 个 Collector", + "restartOffline": "此采集器处于离线状态。待其恢复后请重新启动。", "restartUnsupported": "此 Collector 不接受重启命令", "systemSections": "系统管理的部分", "systemSectionsCaption": "OpAMP 扩展和服务遥测,由 supervisor 和服务器设置", @@ -29327,7 +29357,7 @@ "noVersion": "暂无", "members": "Collector", "membersOnline": "{online}/{total} 在线", - "atDesired": "{total} 个中有 {count} 个处于期望版本", + "atDesired": "{total} 个中有 {count} 个已分配期望版本", "changeVersion": "部署", "deployVersion": "部署版本", "deletedFleet": "已删除的机群", @@ -29442,7 +29472,7 @@ "confirmFixForward": "打开 {config} 编辑器。发布修复后的版本并将此机群切换到该版本;此上线随后将被取代。", "confirmResume": "同一上线将从阶段 {n} 继续。", "confirmRollback": "立即开始回滚到稳定版本 {config} v{version}。已处于该版本的 Collector 不会收到任何内容。", - "confirmRollbackNoStable": "立即开始回滚到稳定版本。", + "confirmRollbackNoStable": "此 Fleet 没有稳定版本,因此发布将结束,其采集器会停止采集,直到您再次部署。", "confirmSkip": "排除 {count} 个失败的 Collector 并继续。它将被标记为已排除,并在下次上线时重新纳入。 | 排除 {count} 个失败的 Collector 并继续。它们将被标记为已排除,并在下次上线时重新纳入。", "confirmed": "已确认", "eventConverged": "阶段 {n} 已收敛", @@ -29479,6 +29509,7 @@ "phaseN": "阶段 {n}", "phaseTimedOut": "已超时", "phaseTimeoutNote": "阶段在 {minutes} 分钟内既未确认也未拒绝时,上线将暂停(机群设置)", + "phaseTimeoutNoteSeconds": "阶段在 {minutes} 分 {seconds} 秒内既未确认也未拒绝,将中止发布(Fleet 设置)", "phaseVerifying": "验证中", "phases": "阶段", "planEmpty": "没有采集器在线,因此发布需等到有采集器连接后才继续", @@ -29619,8 +29650,8 @@ "inheritPlaceholder": "继承({value})", "offlineHeartbeats": "错过心跳后离线", "offlineHeartbeatsHelp": "Collector 在这么多个心跳间隔内没有消息即视为离线", - "offlineRatio": "离线占比事件(%)", - "offlineRatioHelp": "当离线 Collector 的占比超过此值时记录机群事件", + "offlineRatio": "离线比例 (%)", + "offlineRatioHelp": "当该阶段的采集器离线比例超过此值时,将中止该阶段", "outOfRange": "请输入 {min} 到 {max} 之间的数字", "phaseTimeout": "阶段超时(秒)", "phaseTimeoutHelp": "上线阶段在此时间内既未确认也未拒绝则暂停", @@ -29728,6 +29759,7 @@ "publishBlockedChip": "{count} 个错误 · 无法发布 | {count} 个错误 · 无法发布", "saveNewFirst": "请先保存新配置再发布", "saveDraft": "保存草稿", + "publishUnchanged": "这是最新版本。编辑后可发布新版本。", "publishVersion": "发布版本", "modeDraft": "正在编辑草稿", "modeRollingOut": "v{version} 上线中", diff --git a/web/src/locales/languages/zh-TW.json b/web/src/locales/languages/zh-TW.json index 5a7977b818..54c49753aa 100644 --- a/web/src/locales/languages/zh-TW.json +++ b/web/src/locales/languages/zh-TW.json @@ -1,4 +1,17 @@ { + "featureLock": { + "routeTitle": "未包含在您的授權中", + "title": "{feature} 未包含在您的授權中", + "description": "您的管理員可透過更新授權來加入此功能,或聯絡銷售團隊取得包含此功能的授權。", + "thisFeature": "此功能", + "contactSales": "聯絡銷售", + "toastTitle": "未包含在您的授權中", + "toastMessage": "您的授權不包含:{features}。請您的管理員更新授權。", + "toastMessageGeneric": "您的授權不包含此功能。請您的管理員更新授權。", + "bannerMessage": "此功能已鎖定,您的授權必須包含 {feature} 功能。", + "bannerMessageGeneric": "此頁面需要一項不在您授權中的功能。", + "headerLocked": "已鎖定:需要 {feature}" + }, "emptyState": { "illustrations": { "noHistoryYet": "尚無歷史記錄", @@ -3407,6 +3420,22 @@ "contact_name": "聯絡人姓名", "contact_email": "聯絡人電子郵件", "environment_type": "環境類型", + "features": "功能", + "features_all_unlocked": "您的授權已解鎖所有功能。", + "features_summary": "您的授權可解鎖 {ratio}。{free} 項免費功能一律包含在內。 | 您的授權可解鎖 {ratio}。{free} 項免費功能一律包含在內。", + "features_paid_ratio": "{unlocked} 項,共 {paid} 項付費功能 | {unlocked} 項,共 {paid} 項付費功能", + "features_unlocked": "已解鎖", + "features_missing": "未包含在您的授權中", + "features_request_access": "申請存取權", + "features_search": "搜尋 {count} 項功能 | 搜尋所有 {count} 項功能", + "features_filter_all": "全部", + "features_filter_free": "免費", + "features_group_heading": "{heading} · {count}", + "features_no_match": "沒有符合您搜尋的功能", + "features_none": "此群組沒有功能", + "features_free_heading": "免費,所有授權皆包含", + "features_new": "授權後新增", + "features_filter_new": "新增", "request_new_license": "申請新授權", "add_new_license_key": "新增授權金鑰", "refresh_license_limits": "重新整理授權限制", @@ -29299,7 +29328,7 @@ "remove": "移除", "removeManyTitle": "要移除 {count} 個收集器嗎?", "removeMessage": "此操作只會移除該列。仍執行收集器的主機會在下次心跳時再次出現,因此請先在其主機上解除安裝。", - "removeOnlineMessage": "此操作只會移除該列。這些收集器中有 {count} 個處於線上狀態,並會在下次心跳時再次出現;請先在其主機上解除安裝。 | 此操作只會移除這些列。這些收集器中有 {count} 個處於線上狀態,並會在下次心跳時再次出現;請先在其主機上解除安裝。", + "removeOnlineMessage": "這只會移除資料列。這些收集器中有 {count} 個處於線上,並會在下次心跳時重新出現;除非其註冊權杖已耗盡:屆時會保持隱藏並繼續傳送資料。因此請先在其主機上解除安裝。 | 這只會移除資料列。這些收集器中有 {count} 個處於線上,並會在下次心跳時重新出現;除非其註冊權杖已耗盡:屆時會保持隱藏並繼續傳送資料。因此請先在其主機上解除安裝。", "removeTitle": "要移除 {name} 嗎?", "removedCount": "已移除 {count} 個收集器 | 已移除 {count} 個收集器", "rename": "重新命名", @@ -29309,6 +29338,7 @@ "restartManyTitle": "要重新啟動 {count} 個收集器嗎?", "restartMessage": "每個收集器會在收到伺服器的下一則訊息時重新啟動。每台主機的資料收集會短暫暫停。", "restartQueued": "已要求重新啟動 {count} 個收集器 | 已要求重新啟動 {count} 個收集器", + "restartOffline": "此收集器已離線。請待其恢復後再重新啟動。", "restartUnsupported": "此收集器不接受重新啟動指令", "systemSections": "系統管理區段", "systemSectionsCaption": "OpAMP 擴充功能與服務遙測,由 supervisor 與伺服器設定", @@ -29322,7 +29352,7 @@ "noVersion": "尚無", "members": "收集器", "membersOnline": "{online} / {total} 線上", - "atDesired": "{count} / {total} 已在目標版本", + "atDesired": "{count} / {total} 已指派所需版本", "changeVersion": "部署", "deployVersion": "部署版本", "deletedFleet": "已刪除的機群", @@ -29437,7 +29467,7 @@ "confirmFixForward": "開啟 {config} 編輯器。請發佈修正後的版本並將此機群變更為該版本;屆時此推出將被取代。", "confirmResume": "同一個推出會從第 {n} 階段繼續。", "confirmRollback": "立即開始推出以回復到穩定版本 {config} v{version}。已在該版本的收集器不會收到任何內容。", - "confirmRollbackNoStable": "立即開始推出以回復到穩定版本。", + "confirmRollbackNoStable": "此機群沒有穩定版本,因此推出作業將結束,且其收集器會停止收集,直到您再次部署。", "confirmSkip": "排除 {count} 個失敗的收集器並繼續。它會被標記為已排除,並在下次推出時重新納入。 | 排除 {count} 個失敗的收集器並繼續。它們會被標記為已排除,並在下次推出時重新納入。", "confirmed": "已確認", "eventConverged": "第 {n} 階段已收斂", @@ -29474,6 +29504,7 @@ "phaseN": "第 {n} 階段", "phaseTimedOut": "已逾時", "phaseTimeoutNote": "若某階段在 {minutes} 分鐘內既未確認也未拒絕,推出將中止(機群設定)", + "phaseTimeoutNoteSeconds": "若某階段在 {minutes} 分 {seconds} 秒內既未確認也未拒絕,將會中止推出(機群設定)", "phaseVerifying": "驗證中", "phases": "階段", "planEmpty": "目前沒有收集器上線,因此部署會等到有收集器連線後才開始", @@ -29614,8 +29645,8 @@ "inheritPlaceholder": "沿用({value})", "offlineHeartbeats": "遺漏幾次心跳後視為離線", "offlineHeartbeatsHelp": "收集器在這麼多個心跳間隔內未傳送任何訊息即視為離線", - "offlineRatio": "離線比例事件(%)", - "offlineRatioHelp": "當離線的收集器比例超過此值時,記錄一則機群事件", + "offlineRatio": "離線比例(%)", + "offlineRatioHelp": "當離線的收集器占比超過此值時,將中止該階段", "outOfRange": "請輸入 {min} 到 {max} 之間的數字", "phaseTimeout": "階段逾時(秒)", "phaseTimeoutHelp": "推出階段在此時間內既未確認也未拒絕即中止", @@ -29723,6 +29754,7 @@ "publishBlockedChip": "{count} 個錯誤 · 無法發佈 | {count} 個錯誤 · 無法發佈", "saveNewFirst": "發佈前請先儲存新組態", "saveDraft": "儲存草稿", + "publishUnchanged": "這是最新版本。編輯後即可發布新版本。", "publishVersion": "發佈版本", "modeDraft": "編輯草稿", "modeRollingOut": "v{version} 推出中", diff --git a/web/src/services/fleet.mock.ts b/web/src/services/fleet.mock.ts index 6957705e41..ac4523f1e1 100644 --- a/web/src/services/fleet.mock.ts +++ b/web/src/services/fleet.mock.ts @@ -840,8 +840,13 @@ export const fleetMock: FleetApi = { }, deleteFleet: (_org, id) => { if (id === "default") return fail(400, "the default fleet cannot be deleted"); - if (store.collectors.some((c) => c.fleet.id === id)) - return fail(409, "move or remove the fleet's collectors first"); + const collectors = store.collectors.filter((c) => c.fleet.id === id).length; + const tokens = store.tokens.filter((t) => t.fleet?.id === id && !t.revoked).length; + if (collectors || tokens) { + return fail(409, "move or remove the fleet's collectors and revoke its tokens first", { + references: { fleets: 0, collectors, rollouts: 0, tokens }, + }); + } store.fleets = store.fleets.filter((f) => f.id !== id); return reply(undefined as unknown); }, diff --git a/web/src/views/FleetConfigEditor.spec.ts b/web/src/views/FleetConfigEditor.spec.ts index be97a0ff9d..18e04911e8 100644 --- a/web/src/views/FleetConfigEditor.spec.ts +++ b/web/src/views/FleetConfigEditor.spec.ts @@ -353,6 +353,22 @@ describe("FleetConfigEditor", () => { }); describe("publish", () => { + it("refuses to publish the latest version's text until it changes", async () => { + vi.mocked(fleet.getConfig).mockResolvedValue({ + data: detail({ latest_version: 2, versions: [published(2), published(1)] }), + } as any); + wrapper = await mountEditor("edge"); + const button = () => wrapper.find('[data-test="fleet-config-editor-publish"]'); + const editor = wrapper.findComponent({ name: "FleetCodeEditor" }); + expect(button().attributes("disabled")).toBeDefined(); + editor.vm.$emit("update:code", LOSSY + "# fixed\n"); + await flushPromises(); + expect(button().attributes("disabled")).toBeUndefined(); + editor.vm.$emit("update:code", LOSSY); + await flushPromises(); + expect(button().attributes("disabled")).toBeDefined(); + }); + it("toasts the new version and leaves draft mode", async () => { vi.mocked(fleet.publishConfigVersion).mockResolvedValue({ data: { version: 1, warnings: {} }, diff --git a/web/src/views/FleetConfigEditor.vue b/web/src/views/FleetConfigEditor.vue index f7020228e0..aa0af31c95 100644 --- a/web/src/views/FleetConfigEditor.vue +++ b/web/src/views/FleetConfigEditor.vue @@ -44,29 +44,33 @@ along with this program. If not, see . > {{ t("fleet.editor.saveDraft") }} - - {{ t("fleet.editor.publishVersion") }} - + + + {{ t("fleet.editor.publishVersion") }} + + +