diff --git a/apps/ui/js/i18n.js b/apps/ui/js/i18n.js
index 5f77eea..e1b54c2 100644
--- a/apps/ui/js/i18n.js
+++ b/apps/ui/js/i18n.js
@@ -155,13 +155,41 @@ var TRANSLATIONS = {
// Logs page
'logs.title': 'Logs',
- 'logs.subtitle': 'Real-time request and event log',
+ 'logs.subtitle': 'Real-time invocation log for all operations in this workspace.',
'logs.search': 'Search logs...',
'logs.level.all': 'All',
'logs.level.info': 'Info',
'logs.level.warn': 'Warn',
'logs.level.error': 'Error',
'logs.level.debug': 'Debug',
+ 'logs.live': 'Live',
+ 'logs.paused': 'Paused',
+ 'logs.refresh': 'Refresh',
+ 'logs.range.30m': 'Last 30 min',
+ 'logs.range.1h': 'Last 1 hour',
+ 'logs.range.6h': 'Last 6 hours',
+ 'logs.range.24h': 'Last 24 hours',
+ 'logs.range.7d': 'Last 7 days',
+ 'logs.search_messages': 'Search messages…',
+ 'logs.detail.agent': 'Agent',
+ 'logs.detail.request': 'Request preview',
+ 'logs.detail.response': 'Response preview',
+ 'logs.detail.meta': 'Metadata',
+ 'logs.loading.title': 'Loading logs…',
+ 'logs.loading.sub': 'Fetching invocation history for the current workspace.',
+ 'logs.error.title': 'Unable to load logs',
+ 'logs.error.api': 'Admin API is not available',
+ 'logs.error.workspace': 'Workspace is not selected',
+ 'logs.error.load': 'Failed to load logs',
+ 'logs.empty.title': 'No log entries found',
+ 'logs.empty.filtered': 'Try widening the period or clearing the current search and level filters.',
+ 'logs.empty.initial': 'Run tests or published MCP tools to start collecting invocation history.',
+ 'logs.live.on.title': 'Live mode enabled',
+ 'logs.live.on.body': 'Polling logs every 4 seconds.',
+ 'logs.live.off.title': 'Live mode paused',
+ 'logs.live.off.body': 'Automatic polling is paused.',
+ 'logs.refresh.title': 'Logs refreshed',
+ 'logs.refresh.body': 'The latest invocation records were loaded for the current workspace.',
// Usage page
'usage.title': 'Usage',
@@ -446,13 +474,41 @@ var TRANSLATIONS = {
// Logs page
'logs.title': 'Логи',
- 'logs.subtitle': 'Журнал запросов и событий в реальном времени',
+ 'logs.subtitle': 'Живой журнал вызовов по всем операциям этого воркспейса.',
'logs.search': 'Поиск в логах...',
'logs.level.all': 'Все',
'logs.level.info': 'Info',
'logs.level.warn': 'Warn',
'logs.level.error': 'Error',
'logs.level.debug': 'Debug',
+ 'logs.live': 'Live',
+ 'logs.paused': 'Пауза',
+ 'logs.refresh': 'Обновить',
+ 'logs.range.30m': 'Последние 30 мин',
+ 'logs.range.1h': 'Последний 1 час',
+ 'logs.range.6h': 'Последние 6 часов',
+ 'logs.range.24h': 'Последние 24 часа',
+ 'logs.range.7d': 'Последние 7 дней',
+ 'logs.search_messages': 'Поиск по сообщениям…',
+ 'logs.detail.agent': 'Агент',
+ 'logs.detail.request': 'Предпросмотр запроса',
+ 'logs.detail.response': 'Предпросмотр ответа',
+ 'logs.detail.meta': 'Метаданные',
+ 'logs.loading.title': 'Загрузка логов…',
+ 'logs.loading.sub': 'Получаем историю вызовов для текущего воркспейса.',
+ 'logs.error.title': 'Не удалось загрузить логи',
+ 'logs.error.api': 'Admin API недоступен',
+ 'logs.error.workspace': 'Воркспейс не выбран',
+ 'logs.error.load': 'Не удалось загрузить логи',
+ 'logs.empty.title': 'Записей логов не найдено',
+ 'logs.empty.filtered': 'Попробуйте расширить период или сбросить текущий поиск и фильтры уровня.',
+ 'logs.empty.initial': 'Запустите тесты или опубликованные MCP-инструменты, чтобы начать собирать историю вызовов.',
+ 'logs.live.on.title': 'Live режим включен',
+ 'logs.live.on.body': 'Логи опрашиваются каждые 4 секунды.',
+ 'logs.live.off.title': 'Live режим на паузе',
+ 'logs.live.off.body': 'Автоматический опрос остановлен.',
+ 'logs.refresh.title': 'Логи обновлены',
+ 'logs.refresh.body': 'Получены последние записи вызовов для текущего воркспейса.',
// Usage page
'usage.title': 'Использование',
diff --git a/apps/ui/js/logs.js b/apps/ui/js/logs.js
index 0ee9ae0..385e11c 100644
--- a/apps/ui/js/logs.js
+++ b/apps/ui/js/logs.js
@@ -20,6 +20,10 @@ document.addEventListener('DOMContentLoaded', function () {
var liveDot = document.querySelector('.live-dot');
var liveLabel = document.querySelector('.live-label');
+ function tKey(key) {
+ return window.t ? t(key) : key;
+ }
+
function currentWorkspaceId() {
var workspace = window.getCurrentWorkspace ? window.getCurrentWorkspace() : null;
return workspace ? workspace.id : null;
@@ -98,21 +102,21 @@ document.addEventListener('DOMContentLoaded', function () {
function renderLogs() {
if (state.loading && state.logs.length === 0) {
- renderEmpty('Loading logs…', 'Fetching invocation history for the current workspace.');
+ renderEmpty(tKey('logs.loading.title'), tKey('logs.loading.sub'));
return;
}
if (state.loadError) {
- renderEmpty('Unable to load logs', state.loadError);
+ renderEmpty(tKey('logs.error.title'), state.loadError);
return;
}
if (!state.logs.length) {
renderEmpty(
- 'No log entries found',
+ tKey('logs.empty.title'),
state.search || state.level !== 'all'
- ? 'Try widening the period or clearing the current search and level filters.'
- : 'Run tests or published MCP tools to start collecting invocation history.'
+ ? tKey('logs.empty.filtered')
+ : tKey('logs.empty.initial')
);
return;
}
@@ -172,7 +176,7 @@ document.addEventListener('DOMContentLoaded', function () {
if (detail.agentDisplayName || detail.agentSlug) {
var agentLabel = document.createElement('div');
agentLabel.className = 'log-detail-label';
- agentLabel.textContent = 'Agent';
+ agentLabel.textContent = tKey('logs.detail.agent');
expanded.appendChild(agentLabel);
var agentPre = document.createElement('pre');
@@ -183,7 +187,7 @@ document.addEventListener('DOMContentLoaded', function () {
var requestLabel = document.createElement('div');
requestLabel.className = 'log-detail-label';
- requestLabel.textContent = 'Request preview';
+ requestLabel.textContent = tKey('logs.detail.request');
expanded.appendChild(requestLabel);
var requestPre = document.createElement('pre');
@@ -193,7 +197,7 @@ document.addEventListener('DOMContentLoaded', function () {
var responseLabel = document.createElement('div');
responseLabel.className = 'log-detail-label';
- responseLabel.textContent = 'Response preview';
+ responseLabel.textContent = tKey('logs.detail.response');
expanded.appendChild(responseLabel);
var responsePre = document.createElement('pre');
@@ -204,7 +208,7 @@ document.addEventListener('DOMContentLoaded', function () {
if (detail.errorKind || detail.requestId) {
var metaLabel = document.createElement('div');
metaLabel.className = 'log-detail-label';
- metaLabel.textContent = 'Metadata';
+ metaLabel.textContent = tKey('logs.detail.meta');
expanded.appendChild(metaLabel);
var metaPre = document.createElement('pre');
@@ -253,14 +257,14 @@ document.addEventListener('DOMContentLoaded', function () {
async function loadLogs() {
if (!window.CrankApi) {
- state.loadError = 'Admin API is not available';
+ state.loadError = tKey('logs.error.api');
renderLogs();
return;
}
state.workspaceId = currentWorkspaceId();
if (!state.workspaceId) {
- state.loadError = 'Workspace is not selected';
+ state.loadError = tKey('logs.error.workspace');
renderLogs();
return;
}
@@ -276,7 +280,7 @@ document.addEventListener('DOMContentLoaded', function () {
state.openId = null;
}
} catch (error) {
- state.loadError = error.message || 'Failed to load logs';
+ state.loadError = error.message || tKey('logs.error.load');
} finally {
state.loading = false;
renderLogs();
@@ -305,7 +309,7 @@ document.addEventListener('DOMContentLoaded', function () {
liveDot.style.cursor = 'pointer';
}
if (liveLabel) {
- liveLabel.textContent = state.liveMode ? 'Live' : 'Paused';
+ liveLabel.textContent = state.liveMode ? tKey('logs.live') : tKey('logs.paused');
liveLabel.style.color = state.liveMode ? '' : 'var(--text-muted)';
liveLabel.style.cursor = 'pointer';
}
@@ -332,8 +336,8 @@ document.addEventListener('DOMContentLoaded', function () {
startPolling();
if (window.CrankUi) {
window.CrankUi.info(
- state.liveMode ? 'Polling logs every 4 seconds.' : 'Automatic polling is paused.',
- state.liveMode ? 'Live mode enabled' : 'Live mode paused'
+ state.liveMode ? tKey('logs.live.on.body') : tKey('logs.live.off.body'),
+ state.liveMode ? tKey('logs.live.on.title') : tKey('logs.live.off.title')
);
}
}
@@ -360,7 +364,7 @@ document.addEventListener('DOMContentLoaded', function () {
refreshBtn.addEventListener('click', function () {
loadLogs().then(function () {
if (!state.loadError && window.CrankUi) {
- window.CrankUi.info('The latest invocation records were loaded for the current workspace.', 'Logs refreshed');
+ window.CrankUi.info(tKey('logs.refresh.body'), tKey('logs.refresh.title'));
}
});
});