fix(i18n,api): backfill missing token-monitoring keys and fix JWT expiry tz

- i18n: add models.searchProviders, monitoring.tabs.tokens and the
  monitoring.tokens.* block (incl. bucket.hour/day) to es-ES, ja-JP,
  ru-RU, th-TH, vi-VN and zh-Hant, which were missing them and failed
  the Check i18n Keys CI.
- api: generate_jwt_token built 'exp' from a naive datetime.now(), which
  PyJWT validates against UTC — in any timezone ahead of UTC the token
  was already expired at issue time. Use datetime.now(timezone.utc).
This commit is contained in:
RockChinQ
2026-06-13 05:26:18 -04:00
parent a2c6c8201b
commit a97d2040bb
7 changed files with 157 additions and 1 deletions

View File

@@ -82,7 +82,7 @@ class UserService:
payload = {
'user': user_email,
'iss': 'LangBot-' + constants.edition,
'exp': datetime.datetime.now() + datetime.timedelta(seconds=jwt_expire),
'exp': datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(seconds=jwt_expire),
}
return jwt.encode(payload, jwt_secret, algorithm='HS256')

View File

@@ -271,6 +271,7 @@ const esES = {
selectProvider: 'Seleccionar proveedor',
requester: 'Tipo de proveedor',
selectRequester: 'Seleccionar tipo de proveedor',
searchProviders: 'Buscar proveedores...',
langbotModelsDescription: 'Modelos en la nube impulsados por LangBot Space',
credits: 'Créditos',
loginWithSpace: 'Iniciar sesión con Space',
@@ -1236,6 +1237,7 @@ const esES = {
llmCalls: 'Llamadas LLM',
embeddingCalls: 'Llamadas Embedding',
modelCalls: 'Llamadas a modelos',
tokens: 'Monitoreo de Tokens',
sessions: 'Análisis de sesiones',
feedback: 'Comentarios de usuarios',
errors: 'Registros de errores',
@@ -1275,6 +1277,30 @@ const esES = {
avgDuration: 'Duración promedio',
calls: 'Llamadas',
},
tokens: {
totalTokens: 'Tokens totales',
inputTokens: 'Tokens de entrada',
outputTokens: 'Tokens de salida',
avgPerCall: 'Prom. / llamada',
throughput: 'Rendimiento',
tokensPerSec: 'tokens/seg',
errorCalls: 'Llamadas fallidas',
acrossCalls: 'en {{count}} llamadas',
ofTotal: 'de {{count}} en total',
usageOverTime: 'Uso de tokens a lo largo del tiempo',
byModel: 'Por modelo',
model: 'Modelo',
calls: 'Llamadas',
avgLatency: 'Latencia media',
noData: 'No hay uso de tokens en el rango de tiempo seleccionado',
loadError: 'Error al cargar las estadísticas de tokens: {{error}}',
zeroTokenWarning:
'{{count}} llamada(s) exitosa(s) reportaron cero uso de tokens. Esto suele significar que el proveedor upstream no devolvió información de uso; revisa la configuración del proveedor del modelo.',
bucket: {
hour: 'Por hora',
day: 'Por día',
},
},
embeddingCalls: {
title: 'Llamadas Embedding',
model: 'Modelo',

View File

@@ -266,6 +266,7 @@ const jaJP = {
selectProvider: 'プロバイダーを選択',
requester: 'プロバイダータイプ',
selectRequester: 'プロバイダータイプを選択',
searchProviders: 'プロバイダーを検索...',
langbotModelsDescription: 'LangBot Space が提供するクラウドモデル',
credits: 'クレジット',
loginWithSpace: 'Space でログイン',
@@ -1210,6 +1211,7 @@ const jaJP = {
llmCalls: 'LLM呼び出し',
embeddingCalls: 'Embedding呼び出し',
modelCalls: 'モデル呼び出し',
tokens: 'トークン監視',
sessions: 'セッション分析',
feedback: 'ユーザーフィードバック',
errors: 'エラーログ',
@@ -1248,6 +1250,30 @@ const jaJP = {
avgDuration: '平均期間',
calls: '呼び出し',
},
tokens: {
totalTokens: '総トークン数',
inputTokens: '入力トークン',
outputTokens: '出力トークン',
avgPerCall: '平均 / 呼び出し',
throughput: 'スループット',
tokensPerSec: 'トークン/秒',
errorCalls: '失敗した呼び出し',
acrossCalls: '{{count}} 回の呼び出し',
ofTotal: '合計 {{count}} 回',
usageOverTime: 'トークン使用量の推移',
byModel: 'モデル別',
model: 'モデル',
calls: '呼び出し回数',
avgLatency: '平均レイテンシ',
noData: '選択した期間にトークン使用量がありません',
loadError: 'トークン統計の読み込みに失敗しました: {{error}}',
zeroTokenWarning:
'{{count}} 件の成功した呼び出しでトークン使用量が 0 と報告されました。通常これは上流プロバイダーが使用量情報を返さなかったことを意味します。モデルプロバイダーの設定を確認してください。',
bucket: {
hour: '時間単位',
day: '日単位',
},
},
embeddingCalls: {
title: 'Embedding呼び出し',
model: 'モデル',

View File

@@ -269,6 +269,7 @@ const ruRU = {
selectProvider: 'Выберите провайдера',
requester: 'Тип провайдера',
selectRequester: 'Выберите тип провайдера',
searchProviders: 'Поиск провайдеров...',
langbotModelsDescription: 'Облачные модели на базе LangBot Space',
credits: 'Кредиты',
loginWithSpace: 'Войти через Space',
@@ -1213,6 +1214,7 @@ const ruRU = {
llmCalls: 'Вызовы LLM',
embeddingCalls: 'Вызовы Embedding',
modelCalls: 'Вызовы моделей',
tokens: 'Мониторинг токенов',
feedback: 'Обратная связь',
sessions: 'Анализ сессий',
errors: 'Журнал ошибок',
@@ -1251,6 +1253,30 @@ const ruRU = {
avgDuration: 'Средняя длительность',
calls: 'Вызовы',
},
tokens: {
totalTokens: 'Всего токенов',
inputTokens: 'Входные токены',
outputTokens: 'Выходные токены',
avgPerCall: 'Сред. / вызов',
throughput: 'Пропускная способность',
tokensPerSec: 'токенов/сек',
errorCalls: 'Неуспешные вызовы',
acrossCalls: 'за {{count}} вызов(ов)',
ofTotal: 'из {{count}} всего',
usageOverTime: 'Использование токенов со временем',
byModel: 'По модели',
model: 'Модель',
calls: 'Вызовы',
avgLatency: 'Сред. задержка',
noData: 'Нет использования токенов в выбранном диапазоне времени',
loadError: 'Не удалось загрузить статистику токенов: {{error}}',
zeroTokenWarning:
'{{count}} успешный(ых) вызов(ов) сообщили о нулевом использовании токенов. Обычно это означает, что вышестоящий провайдер не вернул информацию об использовании — проверьте настройки провайдера модели.',
bucket: {
hour: 'По часам',
day: 'По дням',
},
},
embeddingCalls: {
title: 'Вызовы Embedding',
model: 'Модель',

View File

@@ -258,6 +258,7 @@ const thTH = {
selectProvider: 'เลือกผู้ให้บริการ',
requester: 'ประเภทผู้ให้บริการ',
selectRequester: 'เลือกประเภทผู้ให้บริการ',
searchProviders: 'ค้นหาผู้ให้บริการ...',
langbotModelsDescription: 'โมเดลคลาวด์ขับเคลื่อนโดย LangBot Space',
credits: 'เครดิต',
loginWithSpace: 'เข้าสู่ระบบด้วย Space',
@@ -1183,6 +1184,7 @@ const thTH = {
llmCalls: 'การเรียก LLM',
embeddingCalls: 'การเรียก Embedding',
modelCalls: 'การเรียกโมเดล',
tokens: 'การติดตาม Token',
sessions: 'การวิเคราะห์เซสชัน',
feedback: 'ความคิดเห็นผู้ใช้',
errors: 'บันทึกข้อผิดพลาด',
@@ -1221,6 +1223,30 @@ const thTH = {
avgDuration: 'ระยะเวลาเฉลี่ย',
calls: 'การเรียก',
},
tokens: {
totalTokens: 'Token ทั้งหมด',
inputTokens: 'Token อินพุต',
outputTokens: 'Token เอาต์พุต',
avgPerCall: 'เฉลี่ย / การเรียก',
throughput: 'ปริมาณงาน',
tokensPerSec: 'tokens/วินาที',
errorCalls: 'การเรียกที่ล้มเหลว',
acrossCalls: 'จาก {{count}} การเรียก',
ofTotal: 'จากทั้งหมด {{count}}',
usageOverTime: 'การใช้ Token ตามช่วงเวลา',
byModel: 'ตามโมเดล',
model: 'โมเดล',
calls: 'การเรียก',
avgLatency: 'เวลาแฝงเฉลี่ย',
noData: 'ไม่มีการใช้ Token ในช่วงเวลาที่เลือก',
loadError: 'โหลดสถิติ Token ล้มเหลว: {{error}}',
zeroTokenWarning:
'มีการเรียกที่สำเร็จ {{count}} ครั้งรายงานการใช้ Token เป็นศูนย์ โดยปกติหมายความว่าผู้ให้บริการต้นทางไม่ได้ส่งข้อมูลการใช้งานกลับมา โปรดตรวจสอบการตั้งค่าผู้ให้บริการโมเดล',
bucket: {
hour: 'รายชั่วโมง',
day: 'รายวัน',
},
},
embeddingCalls: {
title: 'การเรียก Embedding',
model: 'โมเดล',

View File

@@ -266,6 +266,7 @@ const viVN = {
selectProvider: 'Chọn nhà cung cấp',
requester: 'Loại nhà cung cấp',
selectRequester: 'Chọn loại nhà cung cấp',
searchProviders: 'Tìm kiếm nhà cung cấp...',
langbotModelsDescription: 'Mô hình đám mây được cung cấp bởi LangBot Space',
credits: 'Tín dụng',
loginWithSpace: 'Đăng nhập với Space',
@@ -1206,6 +1207,7 @@ const viVN = {
llmCalls: 'Cuộc gọi LLM',
embeddingCalls: 'Cuộc gọi Embedding',
modelCalls: 'Cuộc gọi mô hình',
tokens: 'Giám sát Token',
sessions: 'Phân tích phiên',
feedback: 'Phản hồi người dùng',
errors: 'Nhật ký lỗi',
@@ -1244,6 +1246,30 @@ const viVN = {
avgDuration: 'Thời lượng trung bình',
calls: 'Cuộc gọi',
},
tokens: {
totalTokens: 'Tổng số Token',
inputTokens: 'Token đầu vào',
outputTokens: 'Token đầu ra',
avgPerCall: 'TB / lượt gọi',
throughput: 'Thông lượng',
tokensPerSec: 'token/giây',
errorCalls: 'Lượt gọi thất bại',
acrossCalls: 'trong {{count}} lượt gọi',
ofTotal: 'trên tổng {{count}}',
usageOverTime: 'Mức sử dụng Token theo thời gian',
byModel: 'Theo mô hình',
model: 'Mô hình',
calls: 'Lượt gọi',
avgLatency: 'Độ trễ trung bình',
noData: 'Không có mức sử dụng Token trong khoảng thời gian đã chọn',
loadError: 'Không thể tải thống kê Token: {{error}}',
zeroTokenWarning:
'{{count}} lượt gọi thành công báo cáo mức sử dụng Token bằng 0. Điều này thường có nghĩa là nhà cung cấp thượng nguồn không trả về thông tin sử dụng — hãy kiểm tra cấu hình nhà cung cấp mô hình.',
bucket: {
hour: 'Theo giờ',
day: 'Theo ngày',
},
},
embeddingCalls: {
title: 'Cuộc gọi Embedding',
model: 'Mô hình',

View File

@@ -250,6 +250,7 @@ const zhHant = {
selectProvider: '選擇供應商',
requester: '供應商類型',
selectRequester: '選擇供應商類型',
searchProviders: '搜尋供應商...',
langbotModelsDescription: '由 LangBot Space 提供的雲端模型',
credits: '積分',
loginWithSpace: '使用 Space 登入',
@@ -1146,6 +1147,7 @@ const zhHant = {
llmCalls: 'LLM調用',
embeddingCalls: 'Embedding調用',
modelCalls: '模型調用',
tokens: 'Token 監控',
sessions: '會話分析',
feedback: '使用者反饋',
errors: '錯誤日誌',
@@ -1184,6 +1186,30 @@ const zhHant = {
avgDuration: '平均持續時間',
calls: '呼叫次數',
},
tokens: {
totalTokens: '總 Token 數',
inputTokens: '輸入 Token',
outputTokens: '輸出 Token',
avgPerCall: '平均每次呼叫',
throughput: '吞吐量',
tokensPerSec: 'Token/秒',
errorCalls: '失敗呼叫',
acrossCalls: '共 {{count}} 次呼叫',
ofTotal: '共 {{count}} 次',
usageOverTime: 'Token 用量趨勢',
byModel: '按模型統計',
model: '模型',
calls: '呼叫次數',
avgLatency: '平均延遲',
noData: '所選時間範圍內暫無 Token 用量資料',
loadError: '載入 Token 統計失敗:{{error}}',
zeroTokenWarning:
'偵測到 {{count}} 次成功呼叫未上報 Token 用量(記為 0。這通常表示上游未返回 usage 資訊,請檢查模型供應商設定。',
bucket: {
hour: '按小時',
day: '按天',
},
},
embeddingCalls: {
title: 'Embedding調用',
model: '模型',