fix các bug theo yêu cầu https://fptsoftware362-my.sharepoint.com/❌/g/personal/nampdt_fpt_com/IQAHBJ4A9xqDTLgvt2bhukJEAdRB5LRz2hbJpTivvIiBSYM?wdExp=TEAMS-TREATMENT&web=1&isSPOFile=1&ovuser=f01e930a-b52e-42b1-b70f-a8882b5d043b%2CAnhTNM1%40fpt.com&clickparams=eyJBcHBOYW1lIjoiVGVhbXMtRGVza3RvcCIsIkFwcFZlcnNpb24iOiI0OS8yNjA4MTMxOTMxNyIsIkhhc0ZlZGVyYXRlZFVzZXIiOmZhbHNlfQ%3D%3D --------- Co-authored-by: Duy Le Huu <duylh19@fpt.com> Reviewed-on: #10 Co-authored-by: Anh Tran Nguyen Minh <anhtnm1@fpt.com>
This commit was merged in pull request #10.
This commit is contained in:
+100
-3
@@ -13,10 +13,19 @@ again every time the language changes. Transient dialogs (Settings, Skills,
|
||||
Flow, Permission...) are rebuilt from scratch each time they are opened, so
|
||||
they simply call ``tr()`` while constructing their widgets and need no
|
||||
registration.
|
||||
|
||||
``setText(tr("k"))`` on its own is only correct for the instant it runs, and a
|
||||
screen with dozens of such one-shot calls is where "I picked English and half
|
||||
the screen is still Vietnamese" comes from. The :func:`bind_text` family
|
||||
attaches the key to the widget instead, so every future language change
|
||||
re-applies it — one line per widget, and nothing to remember in a separate
|
||||
``retranslate`` method. Bindings hold the widget WEAKLY, so they are safe for
|
||||
widgets that get rebuilt constantly (Kanban rows, calendar cells).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Callable, Dict, List
|
||||
import weakref
|
||||
from typing import Any, Callable, Dict, Iterable, List, Tuple
|
||||
|
||||
LANGUAGES: Dict[str, str] = {"en": "English", "ja": "日本語", "vi": "Tiếng Việt"}
|
||||
# Short codes shown in the compact top-bar switcher (Settings keeps the full names above).
|
||||
@@ -25,6 +34,8 @@ DEFAULT_LANGUAGE = "vi"
|
||||
|
||||
_current = DEFAULT_LANGUAGE
|
||||
_listeners: List[Callable[[], None]] = []
|
||||
#: (weak ref to the widget, how to re-apply its text) — see :func:`bind_text`.
|
||||
_bindings: List[Tuple["weakref.ref", Callable[[Any], None]]] = []
|
||||
|
||||
# key -> {"en": ..., "ja": ..., "vi": ...}
|
||||
from . import login_dialog as _login_dialog
|
||||
@@ -38,6 +49,8 @@ from . import libreoffice_view as _libreoffice_view
|
||||
from . import agents_admin_tab as _agents_admin_tab
|
||||
from . import monitoring_overview as _monitoring_overview
|
||||
from . import cloud_workspace as _cloud_workspace
|
||||
from . import dialog_buttons as _dialog_buttons
|
||||
from . import connectors as _connectors
|
||||
|
||||
# Gộp theo đúng thứ tự cũ: khoá trùng thì cụm sau thắng, y như khi tất cả
|
||||
# còn nằm chung một dict literal.
|
||||
@@ -52,7 +65,9 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
**_libreoffice_view.STRINGS,
|
||||
**_agents_admin_tab.STRINGS,
|
||||
**_monitoring_overview.STRINGS,
|
||||
**_cloud_workspace.STRINGS,
|
||||
**_cloud_workspace.STRINGS,
|
||||
**_dialog_buttons.STRINGS,
|
||||
**_connectors.STRINGS,
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +79,7 @@ def set_language(lang: str) -> None:
|
||||
if lang == _current:
|
||||
return
|
||||
_current = lang
|
||||
_apply_bindings()
|
||||
for fn in list(_listeners):
|
||||
try:
|
||||
fn()
|
||||
@@ -98,6 +114,87 @@ def on_language_changed(fn: Callable[[], None]) -> None:
|
||||
"""Register a callback that re-applies translations to a persistent widget.
|
||||
|
||||
Called once immediately (to apply the current language) and again on every
|
||||
future call to :func:`set_language`."""
|
||||
future call to :func:`set_language`. For a single widget whose text is one
|
||||
key, prefer :func:`bind_text` and friends — they need no callback of their
|
||||
own and cannot keep a destroyed widget alive."""
|
||||
_listeners.append(fn)
|
||||
fn()
|
||||
|
||||
|
||||
# ---- per-widget bindings -------------------------------------------------
|
||||
|
||||
def _bind(widget: Any, apply: Callable[[Any], None]) -> Any:
|
||||
"""Attach a text re-application to one widget, run it now, return the widget.
|
||||
|
||||
``apply`` takes the widget as its argument rather than closing over it: a
|
||||
closure would keep the widget alive for the life of the process, which is
|
||||
exactly what the weak reference here exists to avoid.
|
||||
|
||||
The widget comes back out so a call site can bind IN PLACE of the one-shot
|
||||
call it replaces — ``bind_text(QLabel(), k)`` where ``QLabel(tr(k))`` was —
|
||||
without spending a line, which several screens here cannot afford (Gate S).
|
||||
"""
|
||||
_bindings.append((weakref.ref(widget), apply))
|
||||
apply(widget)
|
||||
return widget
|
||||
|
||||
|
||||
def _apply_bindings() -> None:
|
||||
"""Re-apply every live binding; drop the ones whose widget is gone.
|
||||
|
||||
Both halves of "gone" are handled: the Python wrapper collected (the weak
|
||||
ref answers None) and the C++ object deleted underneath a live wrapper
|
||||
(``RuntimeError``). Neither may stop the remaining widgets from updating.
|
||||
"""
|
||||
alive: List[Tuple["weakref.ref", Callable[[Any], None]]] = []
|
||||
for ref, apply in _bindings:
|
||||
widget = ref()
|
||||
if widget is None:
|
||||
continue
|
||||
try:
|
||||
apply(widget)
|
||||
except RuntimeError:
|
||||
continue
|
||||
alive.append((ref, apply))
|
||||
_bindings[:] = alive
|
||||
|
||||
|
||||
def bind_text(widget: Any, key: str, **kwargs) -> Any:
|
||||
"""Keep ``widget``'s label on ``key`` through every language change."""
|
||||
return _bind(widget, lambda w: w.setText(tr(key, **kwargs)))
|
||||
|
||||
|
||||
def bind_tip(widget: Any, key: str, **kwargs) -> Any:
|
||||
"""Keep ``widget``'s tooltip on ``key`` through every language change."""
|
||||
return _bind(widget, lambda w: w.setToolTip(tr(key, **kwargs)))
|
||||
|
||||
|
||||
def bind_placeholder(widget: Any, key: str, **kwargs) -> Any:
|
||||
"""Keep an input's placeholder on ``key`` through every language change."""
|
||||
return _bind(widget, lambda w: w.setPlaceholderText(tr(key, **kwargs)))
|
||||
|
||||
|
||||
def bind_items(widget: Any, keys: Iterable[str]) -> Any:
|
||||
"""Keep a combo's item LABELS on ``keys``, by position.
|
||||
|
||||
``setItemText`` on purpose: clearing and re-adding the items would drop the
|
||||
per-item data every caller persists (routing mode, task type) and reset the
|
||||
current selection as a side effect of a translation.
|
||||
"""
|
||||
keys = list(keys)
|
||||
|
||||
def _apply(w: Any) -> None:
|
||||
"""Re-label each item that still exists, leaving its data alone."""
|
||||
for i, key in enumerate(keys[:w.count()]):
|
||||
w.setItemText(i, tr(key))
|
||||
|
||||
return _bind(widget, _apply)
|
||||
|
||||
|
||||
def bind_dynamic(widget: Any, apply: Callable[[], None]) -> Any:
|
||||
"""Bind text that is not one plain key — a count, a name, a joined list.
|
||||
|
||||
``apply`` takes no argument and re-reads whatever it needs itself; the
|
||||
widget is still what decides how long the binding lives.
|
||||
"""
|
||||
return _bind(widget, lambda _w: apply())
|
||||
|
||||
@@ -158,7 +158,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"vi": "Không tìm thấy agent '{name}'."},
|
||||
|
||||
# ---- agents_admin_tab.py — Admin-only agent catalog -------------------
|
||||
"agents_admin.page_title": {"en": "Agents Admin", "ja": "Agents Admin", "vi": "Agents Admin"},
|
||||
"agents_admin.page_title": {"en": "Agents Admin", "ja": "エージェント管理", "vi": "Agents Admin"},
|
||||
"agents_admin.edit_row_tooltip": {"en": "Edit", "ja": "編集", "vi": "Sửa"},
|
||||
"agents_admin.delete_row_tooltip": {"en": "Delete", "ja": "削除", "vi": "Xóa"},
|
||||
"agents_admin.hint": {
|
||||
@@ -179,7 +179,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"en": "Extra instructions this agent always follows (optional)…",
|
||||
"ja": "このエージェントが常に従う追加指示(任意)…",
|
||||
"vi": "Chỉ dẫn bổ sung agent này luôn tuân theo (tùy chọn)…"},
|
||||
"agents_admin.f_provider": {"en": "Provider", "ja": "プロバイダー", "vi": "Provider"},
|
||||
"agents_admin.f_provider": {"en": "Provider", "ja": "プロバイダー", "vi": "Nhà cung cấp"},
|
||||
"agents_admin.provider_default": {
|
||||
"en": "(machine's active provider)", "ja": "(各マシンの現在のプロバイダー)",
|
||||
"vi": "(provider hiện tại của máy)"},
|
||||
|
||||
+72
-16
@@ -9,6 +9,62 @@ from __future__ import annotations
|
||||
from typing import Dict
|
||||
|
||||
STRINGS: Dict[str, Dict[str, str]] = {
|
||||
# ---- man gioi thieu cua khung chat (trang thai rong) ------------------
|
||||
"welcome.greeting": {
|
||||
"en": "Hi {name} — where would you like to start?",
|
||||
"ja": "{name} さん、どこから始めましょうか?",
|
||||
"vi": "Chào {name} — bắt đầu từ đâu?"},
|
||||
"welcome.greeting_anon": {
|
||||
"en": "Where would you like to start?", "ja": "どこから始めましょうか?",
|
||||
"vi": "Bắt đầu từ đâu?"},
|
||||
"welcome.meta_project": {
|
||||
"en": "Working in {name}", "ja": "{name} で作業中",
|
||||
"vi": "Đang làm trong {name}"},
|
||||
"welcome.meta_files": {
|
||||
"en": "{n} file(s) in the local folder", "ja": "ローカルフォルダに {n} 件",
|
||||
"vi": "{n} tệp trong thư mục local"},
|
||||
|
||||
"welcome.card_docs": {
|
||||
"en": "Summarise documents", "ja": "ドキュメントを要約", "vi": "Tóm tắt tài liệu"},
|
||||
"welcome.card_docs_sub": {
|
||||
"en": "Read the files in the local folder", "ja": "ローカルフォルダのファイルを読む",
|
||||
"vi": "Đọc các tệp trong thư mục local"},
|
||||
"welcome.prompt_docs": {
|
||||
"en": "Read the files in this project's folder and summarise each one.",
|
||||
"ja": "このプロジェクトのフォルダにあるファイルを読み、それぞれ要約してください。",
|
||||
"vi": "Đọc các tệp trong thư mục của project này và tóm tắt từng tệp."},
|
||||
|
||||
"welcome.card_data": {
|
||||
"en": "Analyse data", "ja": "データを分析", "vi": "Phân tích dữ liệu"},
|
||||
"welcome.card_data_sub": {
|
||||
"en": "Spreadsheets, CSV, logs", "ja": "表計算、CSV、ログ",
|
||||
"vi": "Bảng tính, CSV, log"},
|
||||
"welcome.prompt_data": {
|
||||
"en": "Analyse the spreadsheet/CSV/log files in this folder and report what stands out.",
|
||||
"ja": "このフォルダの表計算/CSV/ログを分析し、目立つ点を報告してください。",
|
||||
"vi": "Phân tích các tệp bảng tính/CSV/log trong thư mục này và nêu những điểm đáng chú ý."},
|
||||
|
||||
"welcome.card_schedule": {
|
||||
"en": "Set up a schedule", "ja": "スケジュールを作成", "vi": "Dựng lịch chạy"},
|
||||
"welcome.card_schedule_sub": {
|
||||
"en": "Create a daily Schedule Task", "ja": "毎日実行する Schedule Task を作成",
|
||||
"vi": "Tạo Schedule Task hàng ngày"},
|
||||
"welcome.prompt_schedule": {
|
||||
"en": "Help me set up a Schedule Task that runs every day. Ask me what it should do.",
|
||||
"ja": "毎日実行する Schedule Task の作成を手伝ってください。何をするか質問してください。",
|
||||
"vi": "Giúp tôi dựng một Schedule Task chạy hàng ngày. Hỏi tôi nó cần làm gì."},
|
||||
|
||||
"welcome.card_graph": {
|
||||
"en": "Ask GraphRAG", "ja": "GraphRAG に質問", "vi": "Hỏi GraphRAG"},
|
||||
"welcome.card_graph_sub": {
|
||||
"en": "Query this project's knowledge graph",
|
||||
"ja": "このプロジェクトの知識グラフを検索",
|
||||
"vi": "Truy vấn đồ thị tri thức của project"},
|
||||
"welcome.prompt_graph": {
|
||||
"en": "Using this project's knowledge graph, explain how the main pieces fit together.",
|
||||
"ja": "このプロジェクトの知識グラフを使って、主要な要素の関係を説明してください。",
|
||||
"vi": "Dùng đồ thị tri thức của project này, giải thích các phần chính ghép với nhau thế nào."},
|
||||
|
||||
"chatpanel.agent_tooltip": {
|
||||
"en": "Model/agent for THIS tab — independent of the other tab",
|
||||
"ja": "このタブ専用のモデル/エージェント(他のタブとは独立)",
|
||||
@@ -112,8 +168,8 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"composer.manage_skills": {"en": "Manage skills…", "ja": "スキルを管理…", "vi": "Quản lý skill…"},
|
||||
|
||||
# ---- schedule_task_tab.py / task_editor_dialog.py -------------------
|
||||
"schedtask.title": {"en": "Schedule Task", "ja": "Schedule Task", "vi": "Schedule Task"},
|
||||
"schedtask.view.kanban": {"en": "Kanban", "ja": "Kanban", "vi": "Kanban"},
|
||||
"schedtask.title": {"en": "Schedule Task", "ja": "タスクスケジュール", "vi": "Schedule Task"},
|
||||
"schedtask.view.kanban": {"en": "Kanban", "ja": "カンバン", "vi": "Kanban"},
|
||||
"schedtask.view.calendar": {"en": "Calendar", "ja": "カレンダー", "vi": "Lịch"},
|
||||
"schedtask.no_title": {"en": "(untitled)", "ja": "(無題)", "vi": "(chưa có tên)"},
|
||||
"schedtask.cal_today": {"en": "Today", "ja": "今日", "vi": "Hôm nay"},
|
||||
@@ -139,23 +195,23 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"en": "Describe what you want in natural language — AI proposes tasks/schedule/chain, you confirm before anything is created.",
|
||||
"ja": "自然文で説明すると、AIがタスク・スケジュール・チェーンを提案します。確認後に作成されます。",
|
||||
"vi": "Mô tả bằng ngôn ngữ tự nhiên — AI đề xuất task/lịch/chuỗi, bạn xác nhận rồi mới tạo."},
|
||||
"schedtask.no_tasks": {"en": "No tasks", "ja": "タスクなし", "vi": "No tasks"},
|
||||
"schedtask.no_tasks": {"en": "No tasks", "ja": "タスクなし", "vi": "Chưa có task"},
|
||||
"schedtask.no_schedule": {"en": "No schedule", "ja": "スケジュールなし", "vi": "Chưa đặt lịch"},
|
||||
"schedtask.last_success": {"en": "Last: Success", "ja": "前回: 成功", "vi": "Lần cuối: Thành công"},
|
||||
"schedtask.last_failed": {"en": "Last: Failed", "ja": "前回: 失敗", "vi": "Lần cuối: Lỗi"},
|
||||
"schedtask.last_never": {"en": "Last: not run", "ja": "前回: 未実行", "vi": "Lần cuối: chưa chạy"},
|
||||
"schedtask.status.backlog": {"en": "Backlog", "ja": "Backlog", "vi": "Backlog"},
|
||||
"schedtask.status.scheduled": {"en": "Scheduled", "ja": "Scheduled", "vi": "Scheduled"},
|
||||
"schedtask.status.running": {"en": "Running", "ja": "Running", "vi": "Running"},
|
||||
"schedtask.status.waiting_input": {"en": "Waiting Input", "ja": "Waiting Input", "vi": "Waiting Input"},
|
||||
"schedtask.status.done": {"en": "Done", "ja": "Done", "vi": "Done"},
|
||||
"schedtask.status.failed": {"en": "Failed", "ja": "Failed", "vi": "Failed"},
|
||||
"schedtask.status.paused": {"en": "Paused", "ja": "Paused", "vi": "Paused"},
|
||||
"schedtask.status.backlog": {"en": "Backlog", "ja": "バックログ", "vi": "Chờ xử lý"},
|
||||
"schedtask.status.scheduled": {"en": "Scheduled", "ja": "予約済み", "vi": "Đã lên lịch"},
|
||||
"schedtask.status.running": {"en": "Running", "ja": "実行中", "vi": "Đang chạy"},
|
||||
"schedtask.status.waiting_input": {"en": "Waiting Input", "ja": "入力待ち", "vi": "Chờ nhập"},
|
||||
"schedtask.status.done": {"en": "Done", "ja": "完了", "vi": "Hoàn thành"},
|
||||
"schedtask.status.failed": {"en": "Failed", "ja": "失敗", "vi": "Thất bại"},
|
||||
"schedtask.status.paused": {"en": "Paused", "ja": "一時停止", "vi": "Tạm dừng"},
|
||||
"schedtask.type.cowork": {"en": "Cowork", "ja": "Cowork", "vi": "Cowork"},
|
||||
"schedtask.type.co4e_code": {"en": "Code", "ja": "Code", "vi": "Code"},
|
||||
"schedtask.type.flow": {"en": "Flow", "ja": "Flow", "vi": "Flow"},
|
||||
"schedtask.type.script": {"en": "Script", "ja": "Script", "vi": "Script"},
|
||||
"schedtask.type.manual": {"en": "Manual", "ja": "Manual", "vi": "Manual"},
|
||||
"schedtask.type.flow": {"en": "Flow", "ja": "フロー", "vi": "Flow"},
|
||||
"schedtask.type.script": {"en": "Script", "ja": "スクリプト", "vi": "Script"},
|
||||
"schedtask.type.manual": {"en": "Manual", "ja": "手動", "vi": "Thủ công"},
|
||||
"schedtask.priority.low": {"en": "Low", "ja": "低", "vi": "Thấp"},
|
||||
"schedtask.priority.medium": {"en": "Medium", "ja": "中", "vi": "Trung bình"},
|
||||
"schedtask.priority.high": {"en": "High", "ja": "高", "vi": "Cao"},
|
||||
@@ -173,7 +229,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"vi": "Double-click một dòng để mở thư mục artifact của lần chạy đó."},
|
||||
"schedtask.hist_col_time": {"en": "Finished at", "ja": "完了時刻", "vi": "Hoàn thành lúc"},
|
||||
"schedtask.hist_col_status": {"en": "Status", "ja": "状態", "vi": "Trạng thái"},
|
||||
"schedtask.hist_col_run": {"en": "Run ID", "ja": "実行ID", "vi": "Run ID"},
|
||||
"schedtask.hist_col_run": {"en": "Run ID", "ja": "実行ID", "vi": "Mã lần chạy"},
|
||||
"schedtask.hist_col_error": {"en": "Error", "ja": "エラー", "vi": "Lỗi"},
|
||||
"schedtask.menu_create_next": {
|
||||
"en": "Create next task from output", "ja": "出力から次タスクを作成",
|
||||
@@ -205,7 +261,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"schedtask.no_workspace": {"en": "— No workspace —", "ja": "— ワークスペースなし —", "vi": "— Không có workspace —"},
|
||||
"schedtask.f_agent": {"en": "Agent", "ja": "エージェント", "vi": "Agent"},
|
||||
"schedtask.no_agent": {"en": "— No agent preset —", "ja": "— エージェントなし —", "vi": "— Không dùng agent —"},
|
||||
"schedtask.f_provider": {"en": "Provider", "ja": "プロバイダー", "vi": "Provider"},
|
||||
"schedtask.f_provider": {"en": "Provider", "ja": "プロバイダー", "vi": "Nhà cung cấp"},
|
||||
"schedtask.provider_default": {
|
||||
"en": "— Default (Settings) —", "ja": "— 既定(設定)—", "vi": "— Mặc định (Settings) —"},
|
||||
"schedtask.f_model": {"en": "Model", "ja": "モデル", "vi": "Model"},
|
||||
@@ -261,7 +317,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"schedtask.repeat.daily": {"en": "Daily", "ja": "毎日", "vi": "Hằng ngày"},
|
||||
"schedtask.repeat.weekly": {"en": "Weekly", "ja": "毎週", "vi": "Hằng tuần"},
|
||||
"schedtask.repeat.monthly": {"en": "Monthly", "ja": "毎月", "vi": "Hằng tháng"},
|
||||
"schedtask.repeat.cron": {"en": "Cron expression", "ja": "Cron式", "vi": "Cron expression"},
|
||||
"schedtask.repeat.cron": {"en": "Cron expression", "ja": "Cron式", "vi": "Biểu thức cron"},
|
||||
"schedtask.f_task_mode": {"en": "Task type", "ja": "タスク種別", "vi": "Loại task"},
|
||||
# Run kind: an AI agent vs a saved Co4E flow + multi-format import
|
||||
"schedtask.f_run_kind": {"en": "Run", "ja": "実行対象", "vi": "Chạy"},
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Chuỗi hiển thị — nhóm Connector (Giám sát ▸ Công cụ ▸ Connector).
|
||||
|
||||
Tên bốn nhóm catalog trên bảng Connector. Đứng riêng một file vì
|
||||
``libreoffice_view.py`` — nơi giữ các khoá ``connectors.*`` cũ — đã sát trần
|
||||
400 dòng của Gate S; khoá connector thêm mới đi vào đây.
|
||||
|
||||
Ba nhóm CAD / CAE / MS365 là DANH SÁCH TÊN SẢN PHẨM nên giống hệt nhau ở cả ba
|
||||
ngôn ngữ (đã khai vào ``KHOA_KHONG_CAN_DICH`` của test i18n). Chỉ nhóm "Other"
|
||||
có chữ thật để dịch — đúng chỗ người dùng báo còn nguyên tiếng Anh.
|
||||
|
||||
``ui/connectors_panel.py`` tách nhãn tại chuỗi ``" ("`` để in phần trong ngoặc
|
||||
bằng kiểu chữ phụ, nên bản dịch phải dùng ngoặc ĐƠN NỬA CHIỀU RỘNG kèm một dấu
|
||||
cách phía trước — dùng ngoặc full-width ``(`` của tiếng Nhật thì không tách
|
||||
được và cả cụm sẽ in đậm thành một khối.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict
|
||||
|
||||
_CAD = "CAD (NX / CATIA / SolidWorks / AutoCAD)"
|
||||
_CAE = "CAE (ANSA / ABAQUS / HyperWorks / ANSYS)"
|
||||
_MS365 = "MS365 (Microsoft 365 / OneDrive / SharePoint)"
|
||||
|
||||
STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"connectors.cat_cad": {"en": _CAD, "ja": _CAD, "vi": _CAD},
|
||||
"connectors.cat_cae": {"en": _CAE, "ja": _CAE, "vi": _CAE},
|
||||
"connectors.cat_ms365": {"en": _MS365, "ja": _MS365, "vi": _MS365},
|
||||
"connectors.cat_other": {
|
||||
"en": "Other (any generic MCP server)",
|
||||
"ja": "その他 (任意の汎用 MCP サーバー)",
|
||||
"vi": "Khác (MCP server bất kỳ)"},
|
||||
}
|
||||
+24
-2
@@ -93,7 +93,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"en": "Enable the predefined Req→Demo flow feature (off by default).",
|
||||
"ja": "定義済みの Req→Demo フロー機能を有効化(初期値はオフ)。",
|
||||
"vi": "Bật tính năng Flow Req→Demo dựng sẵn (mặc định tắt)."},
|
||||
"code.flow_btn": {"en": "Flow Management", "ja": "Flow Management", "vi": "Flow Management"},
|
||||
"code.flow_btn": {"en": "Flow Management", "ja": "フロー管理", "vi": "Flow Management"},
|
||||
"code.flow_btn_tooltip": {
|
||||
"en": "Build and run a multi-stage flow from requirement to demo.",
|
||||
"ja": "要件からデモまでの多段フローを作成・実行します。",
|
||||
@@ -152,7 +152,8 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
# because until the index existed nothing had to refer to it.
|
||||
"settings.group.general": {"en": "General", "ja": "一般", "vi": "Chung"},
|
||||
"settings.group.provider": {"en": "AI Provider", "ja": "AI プロバイダー", "vi": "Nhà cung cấp AI"},
|
||||
"settings.group.parameter": {"en": "Parameter", "ja": "Parameter", "vi": "Parameter"},
|
||||
"settings.group.parameter": {"en": "Parameter", "ja": "パラメータ", "vi": "Tham số"},
|
||||
"settings.group.about": {"en": "About", "ja": "このアプリについて", "vi": "Giới thiệu"},
|
||||
"settings.param_section_pricing": {
|
||||
"en": "Model pricing", "ja": "モデル価格", "vi": "Bảng giá model"},
|
||||
"settings.pricing_url_label": {
|
||||
@@ -328,6 +329,27 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"settings.group.sandbox": {
|
||||
"en": "Sandbox Security Layer", "ja": "サンドボックス セキュリティ層",
|
||||
"vi": "Sandbox Security Layer"},
|
||||
"settings.sec_enabled": {
|
||||
"en": "Enable Agent Security (command validation)",
|
||||
"ja": "エージェントセキュリティを有効化(コマンド検証)",
|
||||
"vi": "Bật Agent Security (kiểm tra lệnh)"},
|
||||
"settings.sec_enabled_tooltip": {
|
||||
"en": "Turn the whole Agent Security layer on or off.",
|
||||
"ja": "エージェントセキュリティ層全体をオン/オフします。",
|
||||
"vi": "Bật/tắt toàn bộ tầng Agent Security."},
|
||||
"settings.ai_check": {
|
||||
"en": "AI check commands", "ja": "AIによるコマンド検査",
|
||||
"vi": "AI kiểm tra lệnh"},
|
||||
"settings.ai_check_tooltip": {
|
||||
"en": "Let the control agent review a command with AI before it runs.",
|
||||
"ja": "実行前に制御エージェントがAIでコマンドを確認します。",
|
||||
"vi": "Cho control-agent dùng AI xét lệnh trước khi chạy."},
|
||||
"settings.sandbox_pw_unset_title": {
|
||||
"en": "Sandbox Security", "ja": "サンドボックスセキュリティ", "vi": "Bảo mật Sandbox"},
|
||||
"settings.sandbox_pw_unset_body": {
|
||||
"en": "No sandbox password is set yet, so these settings stay locked. Set COWORK_SANDBOX_PASSWORD, or ask your administrator.",
|
||||
"ja": "サンドボックスのパスワードが未設定のため、この設定はロックされたままです。COWORK_SANDBOX_PASSWORD を設定するか、管理者にお問い合わせください。",
|
||||
"vi": "Chưa đặt mật khẩu sandbox nên nhóm thiết lập này vẫn khóa. Hãy đặt COWORK_SANDBOX_PASSWORD, hoặc liên hệ quản trị viên."},
|
||||
"settings.sandbox_confirm_commands": {
|
||||
"en": "Confirm before Cowork runs a command",
|
||||
"ja": "Cowork がコマンドを実行する前に確認する",
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
"""Nhãn cho các nút CHUẨN của Qt (Save/Cancel/OK/Close, Yes/No).
|
||||
|
||||
Qt tự vẽ chữ cho những nút này từ bảng dịch của chính nó, mà ứng dụng không
|
||||
cài ``QTranslator`` nào — nên chúng đứng nguyên tiếng Anh ở cả ba ngôn ngữ.
|
||||
``ui/dialog_buttons.py`` gán lại nhãn bằng các khoá dưới đây.
|
||||
|
||||
Khoá dùng chung cho mọi hộp thoại nên đứng riêng một file, không nhét vào file
|
||||
của một màn hình cụ thể.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict
|
||||
|
||||
STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"dialog.save": {"en": "Save", "ja": "保存", "vi": "Lưu"},
|
||||
"dialog.cancel": {"en": "Cancel", "ja": "キャンセル", "vi": "Hủy"},
|
||||
# "OK" giữ nguyên dạng ở cả ba ngôn ngữ — kể cả bản tiếng Nhật của Qt cũng
|
||||
# dùng "OK". Đã khai vào KHOA_KHONG_CAN_DICH của test i18n.
|
||||
"dialog.ok": {"en": "OK", "ja": "OK", "vi": "OK"},
|
||||
"dialog.close": {"en": "Close", "ja": "閉じる", "vi": "Đóng"},
|
||||
"dialog.yes": {"en": "Yes", "ja": "はい", "vi": "Có"},
|
||||
"dialog.no": {"en": "No", "ja": "いいえ", "vi": "Không"},
|
||||
}
|
||||
+25
-6
@@ -45,8 +45,8 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"schedtask.step_prompt_ph": {"en": "Prompt / command", "ja": "プロンプト/コマンド", "vi": "Prompt / lệnh"},
|
||||
"schedtask.stepexec.cowork": {"en": "Cowork", "ja": "Cowork", "vi": "Cowork"},
|
||||
"schedtask.stepexec.co4e": {"en": "Code", "ja": "Code", "vi": "Code"},
|
||||
"schedtask.stepexec.script": {"en": "Script", "ja": "Script", "vi": "Script"},
|
||||
"schedtask.stepexec.manual": {"en": "Manual", "ja": "Manual", "vi": "Manual"},
|
||||
"schedtask.stepexec.script": {"en": "Script", "ja": "スクリプト", "vi": "Script"},
|
||||
"schedtask.stepexec.manual": {"en": "Manual", "ja": "手動", "vi": "Thủ công"},
|
||||
"schedtask.del_step_tooltip": {"en": "Delete the selected step", "ja": "選択したステップを削除",
|
||||
"vi": "Xóa bước đang chọn"},
|
||||
"schedtask.guide_tooltip": {
|
||||
@@ -168,7 +168,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"en": "Safety: the scheduler will NEVER auto-run this — it parks in Waiting Input until you right-click → Run now.",
|
||||
"ja": "安全: 自動実行されず、Run nowまで待機します。",
|
||||
"vi": "An toàn: scheduler KHÔNG BAO GIỜ tự chạy task này — nó nằm ở Waiting Input tới khi bạn chuột phải → Chạy ngay."},
|
||||
"schedtask.g_input": {"en": "Input", "ja": "入力", "vi": "Input"},
|
||||
"schedtask.g_input": {"en": "Input", "ja": "入力", "vi": "Đầu vào"},
|
||||
"schedtask.f_input_mode": {"en": "Input mode", "ja": "入力モード", "vi": "Chế độ input"},
|
||||
"schedtask.inmode.empty": {"en": "Empty (default)", "ja": "空(既定)", "vi": "Trống (mặc định)"},
|
||||
"schedtask.inmode.manual": {"en": "Manual text", "ja": "手入力テキスト", "vi": "Văn bản nhập tay"},
|
||||
@@ -199,7 +199,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"ja": "各URLを取得し(ベストエフォート)、テキストをコンテキストとして渡します。",
|
||||
"vi": "Mỗi link được tải nội dung (khi có thể) và đưa vào ngữ cảnh cho agent."},
|
||||
"schedtask.f_prev_task": {"en": "Previous task", "ja": "前タスク", "vi": "Task trước"},
|
||||
"schedtask.g_output": {"en": "Output", "ja": "出力", "vi": "Output"},
|
||||
"schedtask.g_output": {"en": "Output", "ja": "出力", "vi": "Đầu ra"},
|
||||
"schedtask.f_output_mode": {"en": "Output mode", "ja": "出力モード", "vi": "Chế độ output"},
|
||||
"schedtask.g_dependency": {"en": "Dependency / Next task", "ja": "依存 / 次タスク", "vi": "Phụ thuộc / Task tiếp theo"},
|
||||
"schedtask.f_next_task": {"en": "Next task", "ja": "次タスク", "vi": "Task tiếp theo"},
|
||||
@@ -244,8 +244,8 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"ja": "プレビュー(確認するまで作成されません):",
|
||||
"vi": "Xem trước (chưa tạo gì cho tới khi bạn xác nhận):"},
|
||||
"schedtask.ai_confirm": {"en": "Create tasks", "ja": "タスクを作成", "vi": "Tạo các task"},
|
||||
"schedtask.tab_ai": {"en": "AI gen task", "ja": "AIタスク生成", "vi": "AI gen task"},
|
||||
"schedtask.tab_import": {"en": "Import", "ja": "インポート", "vi": "Import"},
|
||||
"schedtask.tab_ai": {"en": "AI gen task", "ja": "AIタスク生成", "vi": "Tạo task bằng AI"},
|
||||
"schedtask.tab_import": {"en": "Import", "ja": "インポート", "vi": "Nhập"},
|
||||
"schedtask.export_template_btn": {
|
||||
"en": "Create Excel template…", "ja": "Excelテンプレートを作成…",
|
||||
"vi": "Tạo template Excel…"},
|
||||
@@ -339,4 +339,23 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"en": "No usage recorded in this period yet — run a chat or a task first.",
|
||||
"ja": "この期間の使用記録はまだありません。チャットやタスクを実行してください。",
|
||||
"vi": "Chưa có dữ liệu sử dụng trong giai đoạn này — hãy chạy chat hoặc task trước."},
|
||||
# Lỗi hợp lệ hoá phụ thuộc/chuỗi task: ``core/tasks.py`` trả về KHOÁ, nơi
|
||||
# hiển thị mới gọi ``tr()`` (tầng core không biết ngôn ngữ đang chọn).
|
||||
"schedtask.err_self_wait": {
|
||||
"en": "A task cannot wait for itself.", "ja": "タスクは自分自身を待てません。",
|
||||
"vi": "Một task không thể chờ chính nó."},
|
||||
"schedtask.err_wait_cycle": {
|
||||
"en": "This would create a circular wait between tasks.",
|
||||
"ja": "タスク間で待ち合わせが循環してしまいます。",
|
||||
"vi": "Việc này sẽ tạo vòng chờ luẩn quẩn giữa các task."},
|
||||
"schedtask.err_self_chain": {
|
||||
"en": "A task cannot chain to itself.", "ja": "タスクは自分自身に連結できません。",
|
||||
"vi": "Một task không thể nối tiếp chính nó."},
|
||||
"schedtask.err_next_missing": {
|
||||
"en": "Next task does not exist.", "ja": "次のタスクが存在しません。",
|
||||
"vi": "Task kế tiếp không tồn tại."},
|
||||
"schedtask.err_chain_cycle": {
|
||||
"en": "This would create a circular task chain.",
|
||||
"ja": "タスクの連結が循環してしまいます。",
|
||||
"vi": "Việc này sẽ tạo chuỗi task luẩn quẩn."},
|
||||
}
|
||||
|
||||
@@ -134,6 +134,45 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"vi": "Bật/tắt các tool tích hợp bên dưới. Tool bị tắt sẽ bị loại khỏi bộ công cụ của agent. "
|
||||
"Connector MCP / REST-API được thiết lập ở tab con Connector."},
|
||||
"tools_admin.refresh": {"en": "Refresh", "ja": "更新", "vi": "Làm mới"},
|
||||
# Mô tả tool HIỂN THỊ trên thẻ, một khoá cho mỗi ``TOOL_SPECS[].name``.
|
||||
# KHÔNG dùng ``spec.description``: chuỗi đó là mô tả gửi cho mô hình trong
|
||||
# schema function-calling, phải giữ nguyên tiếng Anh và viết cho máy đọc.
|
||||
"tools_admin.desc.read_file": {
|
||||
"en": "Read the contents of a text file in the working folder.",
|
||||
"ja": "作業フォルダー内のテキストファイルの内容を読み取ります。",
|
||||
"vi": "Đọc nội dung một tệp văn bản trong thư mục làm việc."},
|
||||
"tools_admin.desc.list_dir": {
|
||||
"en": "List files and subfolders at a path (defaults to the workdir root).",
|
||||
"ja": "指定パスのファイルとサブフォルダーを一覧表示します(既定は作業フォルダー直下)。",
|
||||
"vi": "Liệt kê tệp và thư mục con tại một đường dẫn (mặc định là gốc thư mục làm việc)."},
|
||||
"tools_admin.desc.write_file": {
|
||||
"en": "Create a new file or fully rewrite one. For small edits, prefer edit_file.",
|
||||
"ja": "ファイルを新規作成、または全体を書き換えます。小さな修正には edit_file を使います。",
|
||||
"vi": "Tạo tệp mới hoặc ghi đè toàn bộ. Sửa nhỏ thì nên dùng edit_file."},
|
||||
"tools_admin.desc.edit_file": {
|
||||
"en": "Replace an exact snippet inside an existing file — preferred for small edits.",
|
||||
"ja": "既存ファイル内の特定の箇所を置き換えます。小さな修正に適しています。",
|
||||
"vi": "Thay chính xác một đoạn trong tệp có sẵn — hợp cho các sửa đổi nhỏ."},
|
||||
"tools_admin.desc.run_command": {
|
||||
"en": "Run a shell command in the working folder and return its output.",
|
||||
"ja": "作業フォルダーでシェルコマンドを実行し、その出力を返します。",
|
||||
"vi": "Chạy một lệnh shell trong thư mục làm việc và trả về kết quả."},
|
||||
"tools_admin.desc.install_package": {
|
||||
"en": "Install a Python package (pip) so the task can use a missing library.",
|
||||
"ja": "不足しているライブラリを使えるよう Python パッケージ(pip)をインストールします。",
|
||||
"vi": "Cài gói Python (pip) để tác vụ dùng được thư viện còn thiếu."},
|
||||
"tools_admin.desc.fetch_url": {
|
||||
"en": "Fetch a web page or online document by URL and return its text.",
|
||||
"ja": "URL から Web ページやオンライン文書を取得し、テキストを返します。",
|
||||
"vi": "Tải trang web hoặc tài liệu trực tuyến theo URL và trả về nội dung văn bản."},
|
||||
"tools_admin.desc.jira_search": {
|
||||
"en": "Search Jira issues with a JQL query and return a summary list. Read-only.",
|
||||
"ja": "JQL クエリで Jira の課題を検索し、一覧を返します。読み取り専用です。",
|
||||
"vi": "Tìm issue Jira bằng truy vấn JQL và trả về danh sách tóm tắt. Chỉ đọc."},
|
||||
"tools_admin.desc.jira_get_issue": {
|
||||
"en": "Read one Jira issue's details by key, e.g. ABX-123.",
|
||||
"ja": "キー(例: ABX-123)を指定して Jira 課題の詳細を読み取ります。",
|
||||
"vi": "Đọc chi tiết một issue Jira theo mã, ví dụ ABX-123."},
|
||||
"tools_admin.url_fetch_group": {
|
||||
"en": "Web access (fetch_url)", "ja": "Webアクセス (fetch_url)",
|
||||
"vi": "Truy cập web (fetch_url)"},
|
||||
@@ -268,6 +307,12 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"co4e.custom": {"en": "custom", "ja": "カスタム", "vi": "tùy chỉnh"},
|
||||
"co4e.parallel_node": {"en": "Parallel (fan-out)", "ja": "並列(ファンアウト)", "vi": "Song song (fan-out)"},
|
||||
"co4e.add_step": {"en": "Add step", "ja": "ステップ追加", "vi": "Thêm bước"},
|
||||
"co4e.canvas_add_next": {
|
||||
"en": "Add next step", "ja": "次のステップを追加", "vi": "Thêm bước kế"},
|
||||
"co4e.canvas_connect_from": {
|
||||
"en": "Connect from here", "ja": "ここから接続", "vi": "Nối từ đây"},
|
||||
"co4e.canvas_delete_edge": {
|
||||
"en": "Delete connection", "ja": "接続を削除", "vi": "Xóa liên kết"},
|
||||
"co4e.fit": {"en": "Fit", "ja": "全体表示", "vi": "Vừa màn hình"},
|
||||
"co4e.fit_tooltip": {
|
||||
"en": "Auto-fit: zoom to show every step", "ja": "自動フィット:全ステップを表示",
|
||||
|
||||
@@ -149,8 +149,14 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"app.provider": {"en": "Provider:", "ja": "プロバイダー:", "vi": "Nhà cung cấp:"},
|
||||
"app.language": {"en": "Language:", "ja": "言語:", "vi": "Ngôn ngữ:"},
|
||||
"app.settings": {"en": "Settings", "ja": "設定", "vi": "Cài đặt"},
|
||||
"app.tab.dashboard": {"en": "Dashboard", "ja": "Dashboard", "vi": "Dashboard"},
|
||||
"app.tab.schedule": {"en": "Schedule Task", "ja": "Schedule Task", "vi": "Schedule Task"},
|
||||
# Shown on the cover while a language switch blocks the GUI thread. It is
|
||||
# deliberately read BEFORE the switch, so it appears in the language the
|
||||
# user is leaving — the only one they can still read at that moment.
|
||||
"app.lang.switching": {
|
||||
"en": "Switching language…", "ja": "言語を切り替えています…",
|
||||
"vi": "Đang đổi ngôn ngữ…"},
|
||||
"app.tab.dashboard": {"en": "Dashboard", "ja": "ダッシュボード", "vi": "Dashboard"},
|
||||
"app.tab.schedule": {"en": "Schedule Task", "ja": "タスクスケジュール", "vi": "Schedule Task"},
|
||||
"app.tab.cowork": {"en": "Cowork", "ja": "Cowork", "vi": "Cowork"},
|
||||
"app.tab.code": {"en": "Code", "ja": "Code", "vi": "Code"},
|
||||
"app.tab.structure": {"en": "GraphRAG", "ja": "GraphRAG", "vi": "GraphRAG"},
|
||||
@@ -158,7 +164,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"app.tab.monitoring": {"en": "Monitoring", "ja": "モニタリング", "vi": "Giám sát"},
|
||||
"app.nav.collapse_tooltip": {"en": "Collapse menu to icons only", "ja": "メニューをアイコンのみに折りたたむ", "vi": "Thu gọn menu về icon"},
|
||||
"app.nav.expand_tooltip": {"en": "Expand menu", "ja": "メニューを展開", "vi": "Mở rộng menu"},
|
||||
"app.nav.menu_label": {"en": "MENU", "ja": "MENU", "vi": "MENU"},
|
||||
"app.nav.menu_label": {"en": "MENU", "ja": "メニュー", "vi": "MENU"},
|
||||
# Shown on the rail rows the project gate disables (Cowork, GraphRAG) —
|
||||
# they stay listed and greyed instead of disappearing from the menu.
|
||||
"app.nav.needs_project": {
|
||||
|
||||
@@ -45,6 +45,28 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"ファイアウォールではありません。上のコマンドホワイトリストと併用してください。",
|
||||
"vi": "Kiểm soát ở tầng chính sách (trỏ biến môi trường proxy vào hố đen) — không phải "
|
||||
"firewall tầng kernel. Kết hợp với whitelist lệnh ở trên để phòng thủ nhiều lớp."},
|
||||
"settings.sandbox_pw_label": {
|
||||
"en": "Sandbox Security Password", "ja": "サンドボックスセキュリティのパスワード",
|
||||
"vi": "Mật khẩu Bảo mật Sandbox"},
|
||||
"settings.sandbox_pw_placeholder": {
|
||||
"en": "Enter password to edit sandbox settings",
|
||||
"ja": "サンドボックス設定を変更するにはパスワードを入力してください",
|
||||
"vi": "Nhập mật khẩu để sửa thiết lập sandbox"},
|
||||
"settings.sandbox_unlock_btn": {"en": "Unlock", "ja": "ロック解除", "vi": "Mở khoá"},
|
||||
"settings.sandbox_locked": {
|
||||
"en": "Locked (changes disabled)", "ja": "ロック中(変更できません)",
|
||||
"vi": "Đang khoá (không sửa được)"},
|
||||
"settings.sandbox_unlocked": {
|
||||
"en": "Unlocked", "ja": "ロック解除済み", "vi": "Đã mở khoá"},
|
||||
"settings.sandbox_unlocked_body": {
|
||||
"en": "Sandbox settings unlocked.", "ja": "サンドボックス設定のロックを解除しました。",
|
||||
"vi": "Đã mở khoá thiết lập sandbox."},
|
||||
"settings.sandbox_pw_wrong_title": {
|
||||
"en": "Wrong Password", "ja": "パスワードが違います", "vi": "Sai mật khẩu"},
|
||||
"settings.sandbox_pw_wrong_body": {
|
||||
"en": "Password incorrect. Sandbox settings remain locked.",
|
||||
"ja": "パスワードが正しくありません。サンドボックス設定はロックされたままです。",
|
||||
"vi": "Mật khẩu không đúng. Thiết lập sandbox vẫn bị khoá."},
|
||||
"settings.sandbox_unlimited": {"en": "Unlimited", "ja": "無制限", "vi": "Không giới hạn"},
|
||||
"settings.sandbox_cpu_label": {"en": "CPU limit", "ja": "CPU 制限", "vi": "Giới hạn CPU"},
|
||||
"settings.sandbox_memory_label": {"en": "Memory limit", "ja": "メモリ制限", "vi": "Giới hạn bộ nhớ"},
|
||||
|
||||
+24
-2
@@ -46,7 +46,17 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"vi": "Project của hội thoại này không còn tồn tại — không thể mở."},
|
||||
"workspace.name": {"en": "Name", "ja": "名前", "vi": "Tên"},
|
||||
"workspace.description": {"en": "Description", "ja": "説明", "vi": "Mô tả"},
|
||||
"workspace.instructions": {"en": "Instructions", "ja": "Instructions", "vi": "Instructions"},
|
||||
"workspace.instructions": {"en": "Instructions", "ja": "指示", "vi": "Hướng dẫn"},
|
||||
"workspace.edit_project": {"en": "Edit project", "ja": "プロジェクトを編集", "vi": "Sửa project"},
|
||||
"workspace.menu_open": {"en": "Open", "ja": "開く", "vi": "Mở"},
|
||||
"workspace.menu_edit": {"en": "Edit", "ja": "編集", "vi": "Sửa"},
|
||||
"workspace.menu_delete": {"en": "Delete", "ja": "削除", "vi": "Xóa"},
|
||||
"workspace.name_taken_title": {
|
||||
"en": "Name already used", "ja": "名前が重複しています", "vi": "Tên đã được dùng"},
|
||||
"workspace.name_taken_body": {
|
||||
"en": "Another project is already called \"{name}\". Project names must be unique — the list shows nothing but the name, so two of them cannot be told apart.",
|
||||
"ja": "「{name}」という名前のプロジェクトが既にあります。一覧には名前しか出ないため、同じ名前が二つあると区別できません。",
|
||||
"vi": "Đã có project khác tên \"{name}\". Tên project phải khác nhau — danh sách chỉ hiện tên, trùng tên là không phân biệt được."},
|
||||
"workspace.instructions_placeholder": {
|
||||
"en": "e.g. \"All answers in Vietnamese. We are building the X reporting tool; always follow the naming rules …\"",
|
||||
"ja": "例:「回答はすべて日本語で。X レポートツールを開発中。命名規則に従うこと …」",
|
||||
@@ -69,7 +79,10 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"app.status.ready": {"en": "Ready.", "ja": "準備完了。", "vi": "Sẵn sàng."},
|
||||
"app.status.using_provider": {"en": "Using {label}.", "ja": "{label} を使用中。", "vi": "Đang dùng {label}."},
|
||||
"app.status.settings_saved": {"en": "Settings saved.", "ja": "設定を保存しました。", "vi": "Đã lưu cài đặt."},
|
||||
"app.credit": {"en": "Made by QuanDH14", "ja": "Made by QuanDH14", "vi": "Made by QuanDH14"},
|
||||
# Con số lấy từ ``cowork_local.__version__`` — một nguồn duy nhất cho tiêu
|
||||
# đề cửa sổ, tab Giới thiệu và góc dưới phải. Giữ nguyên dạng ở cả ba ngôn
|
||||
# ngữ (đã khai vào KHOA_KHONG_CAN_DICH).
|
||||
"app.version": {"en": "Version {v}", "ja": "Version {v}", "vi": "Version {v}"},
|
||||
"app.tray.open": {"en": "Open Cowork Local", "ja": "Cowork Local を開く", "vi": "Mở Cowork Local"},
|
||||
"app.tray.quit": {"en": "Quit", "ja": "終了", "vi": "Thoát"},
|
||||
"app.tray.running_body": {
|
||||
@@ -187,6 +200,15 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"chat.provider_default_short": {
|
||||
"en": "the provider's default model", "ja": "プロバイダー既定のモデル",
|
||||
"vi": "model mặc định của provider"},
|
||||
"chat.provider_default_item": {
|
||||
"en": "(provider default)", "ja": "(プロバイダー既定)",
|
||||
"vi": "(mặc định của provider)"},
|
||||
"chat.record_audio_start": {
|
||||
"en": "Record Voice Note", "ja": "ボイスメモを録音", "vi": "Ghi âm ghi chú"},
|
||||
"chat.record_audio_stop": {
|
||||
"en": "Stop Recording", "ja": "録音を停止", "vi": "Dừng ghi âm"},
|
||||
"chat.record_audio_cancel": {
|
||||
"en": "Cancel recording", "ja": "録音をキャンセル", "vi": "Hủy ghi âm"},
|
||||
"chat.delete_link": {"en": "Delete", "ja": "削除", "vi": "Xóa"},
|
||||
"chat.delete_tooltip": {
|
||||
"en": "Delete this message and its input/output files",
|
||||
|
||||
@@ -123,7 +123,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"vi": "Không phân tích được template này. Kiểm tra file .pptx/.xlsx hợp lệ và provider AI trong Settings hoạt động tốt, hoặc tự thêm skill thủ công."},
|
||||
|
||||
# ---- flow_dialog.py -----------------------------------------------
|
||||
"flow.title": {"en": "Flow Management", "ja": "Flow Management", "vi": "Flow Management"},
|
||||
"flow.title": {"en": "Flow Management", "ja": "フロー管理", "vi": "Flow Management"},
|
||||
"flow.tab_flow": {"en": "Flow", "ja": "フロー", "vi": "Flow"},
|
||||
"flow.tab_agents": {"en": "Agents", "ja": "エージェント", "vi": "Agents"},
|
||||
"flow.tab_skills": {"en": "Skills", "ja": "スキル", "vi": "Skills"},
|
||||
@@ -140,7 +140,7 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"flow.task_prompt": {"en": "Task (prompt)", "ja": "タスク(プロンプト)", "vi": "Nhiệm vụ (prompt)"},
|
||||
"flow.skill": {"en": "Skill", "ja": "スキル", "vi": "Skill"},
|
||||
"flow.agent": {"en": "AI provider", "ja": "AI プロバイダー", "vi": "AI provider"},
|
||||
"flow.model_label": {"en": "Agent:", "ja": "Agent:", "vi": "Agent:"},
|
||||
"flow.model_label": {"en": "Agent:", "ja": "エージェント:", "vi": "Agent:"},
|
||||
"flow.default_model": {"en": "(provider default)", "ja": "(プロバイダー既定)", "vi": "(mặc định của provider)"},
|
||||
"flow.gen_task_from_hint": {"en": "Generate task from hint", "ja": "ヒントからタスクを生成", "vi": "Tạo task từ gợi ý"},
|
||||
"flow.gen_task_tooltip": {
|
||||
@@ -336,6 +336,9 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
||||
"vi": "Nhấp node để mở thư mục, hoặc hỏi agent về đồ thị."},
|
||||
"structure.pick_folder_title": {"en": "Choose folder", "ja": "フォルダを選択", "vi": "Chọn thư mục"},
|
||||
"structure.scanning": {"en": "Scanning structure…", "ja": "構造をスキャン中…", "vi": "Đang quét cấu trúc…"},
|
||||
"structure.loading_view": {
|
||||
"en": "Loading the graph view…", "ja": "グラフビューを読み込み中…",
|
||||
"vi": "Đang tải khung đồ thị…"},
|
||||
"structure.scan_error": {"en": "Scan error: {err}", "ja": "スキャンエラー: {err}", "vi": "Lỗi khi quét: {err}"},
|
||||
"structure.graph_summary": {"en": "Graph: {nodes} nodes, {edges} edges.{note}", "ja": "グラフ: ノード {nodes} 個、エッジ {edges} 個。{note}", "vi": "Đồ thị: {nodes} node, {edges} cạnh.{note}"},
|
||||
"structure.truncated_note": {"en": " (truncated — too many nodes)", "ja": " (切り捨て:ノードが多すぎます)", "vi": " (đã cắt bớt — quá nhiều node)"},
|
||||
|
||||
Reference in New Issue
Block a user