Files
1be6047c8a feat(tracker): field-prefixed search, inline filter chips and zero-hit empty state (#10998)
* feat(tracker): field-prefixed search, inline filter chips and zero-hit empty state

Adds SearchInputAdvanced (field:value prefixes routed to Elasticsearch query_string), match highlighting, inline filter chips with overflow popover, a reusable zero-hit empty state in view-resources, and search-scope/highlight view options for List and Kanban.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>

* refactor(tracker-search): address review follow-ups on search/filter rework

Shared, non-storage-specific field list, test-folder conventions, locale
coverage, single regex source and an owner-token gate for the result count.

- core: add shared `fullTextSearchFields` constant next to
  FullTextSearchContext as the single source of truth for the full-text
  fields exposed to `field:value` targeting. The client encoder derives
  ES_NATIVE_FIELDS from it and the elastic adapter derives KNOWN_FIELD_RE
  from it, replacing the two "KEEP IN SYNC" copies. Per-field boost weights
  stay a local adapter detail.
- tests: move the five co-located tests into each package's existing test
  folder convention (ui `__test__`, view-resources `__tests__`) and fix the
  relative imports.
- i18n: translate the new tracker search/filter strings in the remaining
  locales (zh, ja, ko, cs, es, fr, it, pt, pt-br, tr), reusing each file's
  existing terminology; ICU placeholders left unchanged.
- encoder: hoist the reserved-character class into one constant and build two
  RegExp instances from it (non-global for `.test()`, global for `.replace()`)
  to avoid the shared-lastIndex trap.
- view-resources: guard `resultIssueCountStore` writes with an owner-token
  gate so a superseded viewlet can no longer clobber the active viewlet's
  count; List/KanbanView claim and release, IssuesView resets through the
  current owner. Assumes a single active IssuesView surface.
- view-resources: make result-count reporting opt-in via a new
  `reportResultCount` prop on List (default true). Embedded, non-primary List
  instances (sub-issues / related issues in the issue edit panel, routed
  through SubIssueList) pass false and never claim the owner token, so opening
  and closing an issue can no longer strand the primary Issues viewlet with a
  dead token — the zero-hit SearchEmptyState card renders again afterwards. Add
  a regression test covering the opted-out embedded consumer.
- elastic: escape every regex metacharacter (not just `.`) when building
  KNOWN_FIELD_RE from `fullTextSearchFields`, so a future field name carrying
  another metacharacter cannot silently corrupt the alternation. Behaviour for
  the current fields is unchanged.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>

* refactor(tracker-search): centralize regex escaping and lock down result-count store

- Share escapeRegExp from @hcengineering/core so the client encoder and the server elastic adapter escape the fulltext field list identically, not just dots on the client.

- Export resultIssueCountStore as a read-only Readable; the owner-token gate functions (setResultCount / resetResultCount / releaseResultCountOwner) are now the only write path.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>

---------

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Co-authored-by: Michael Uray <michaeluray@users.noreply.github.com>
Co-authored-by: Artyom Savchenko <armisav@gmail.com>
2026-08-11 19:09:33 +07:00

311 lines
12 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"string": {
"TrackerApplication": "追踪器",
"Projects": "您的项目",
"More": "更多",
"Default": "默认",
"MakeDefault": "设为默认",
"Delete": "删除",
"Open": "打开",
"Members": "成员",
"Inbox": "收件箱",
"MyIssues": "我的问题",
"ViewIssue": "查看问题",
"IssueCreated": "问题已创建",
"Issues": "问题",
"Views": "视图",
"Active": "活跃",
"AllIssues": "所有问题",
"ActiveIssues": "活跃问题",
"BacklogIssues": "积压",
"Backlog": "积压",
"Board": "看板",
"Components": "组件",
"AllComponents": "全部",
"BacklogComponents": "积压",
"ActiveComponents": "活跃",
"ClosedComponents": "已关闭",
"NewComponent": "新组件",
"CreateComponent": "创建组件",
"ComponentNamePlaceholder": "组件名称",
"ComponentDescriptionPlaceholder": "描述(可选)",
"ComponentLead": "负责人",
"ComponentMembers": "成员",
"StartDate": "开始日期",
"TargetDate": "目标日期",
"Planned": "已计划",
"InProgress": "进行中",
"Paused": "暂停",
"Completed": "已完成",
"Canceled": "已取消",
"CreateProject": "创建项目",
"NewProject": "新项目",
"ProjectTitle": "项目标题",
"ProjectTitlePlaceholder": "新项目",
"UsedInIssueIDs": "引用问题ID",
"Identifier": "标识符",
"Import": "导入",
"ProjectIdentifier": "项目标识符",
"IdentifierExists": "项目标识符已存在",
"ProjectIdentifierPlaceholder": "PRJCT",
"ChooseIcon": "选择图标",
"AddIssue": "添加问题",
"NewIssue": "新问题",
"NewIssuePlaceholder": "新问题",
"ResumeDraft": "恢复草稿",
"SaveIssue": "创建问题",
"SetPriority": "设置优先级…",
"SetStatus": "设置状态…",
"SelectIssue": "选择问题",
"Priority": "优先级",
"NoPriority": "无优先级",
"Urgent": "紧急",
"High": "高",
"Medium": "中",
"Low": "低",
"Unassigned": "未分配",
"Back": "返回",
"List": "列表",
"NumberLabels": "{count, plural, =0 {无标签} =1 {1 个标签} other {# 个标签}}",
"CategoryBacklog": "积压",
"CategoryUnstarted": "未开始",
"CategoryStarted": "已开始",
"CategoryCompleted": "已完成",
"CategoryCanceled": "已取消",
"Title": "标题",
"Name": "名称",
"Description": "描述",
"Status": "状态",
"Number": "编号",
"Assignee": "受理人",
"AssignTo": "分配给…",
"AssignedTo": "分配给 {value}",
"Parent": "父问题",
"SetParent": "设置父问题…",
"ChangeParent": "更改父问题…",
"RemoveParent": "移除父问题",
"OpenParent": "打开父问题",
"SubIssues": "子问题",
"SubIssuesList": "子问题 ({subIssues})",
"OpenSubIssues": "打开子问题",
"AddSubIssues": "添加子问题",
"BlockedBy": "被阻塞",
"RelatedTo": "相关",
"Comments": "评论",
"Attachments": "附件",
"Labels": "标签",
"Component": "组件",
"Space": "",
"SetDueDate": "设置截止日期…",
"ChangeDueDate": "更改截止日期…",
"ModificationDate": "更新于 {value}",
"Project": "项目",
"Issue": "问题",
"SubIssue": "子问题",
"Document": "",
"DocumentIcon": "",
"DocumentColor": "",
"Rank": "排名",
"TypeIssuePriority": "问题优先级",
"IssueTitlePlaceholder": "问题标题",
"SubIssueTitlePlaceholder": "子问题标题",
"IssueDescriptionPlaceholder": "添加描述…",
"SubIssueDescriptionPlaceholder": "添加子问题描述",
"AddIssueTooltip": "添加问题…",
"NewIssueDialogClose": "您想要关闭此对话框吗?",
"NewIssueDialogCloseNote": "所有更改将会丢失",
"RemoveComponentDialogClose": "删除组件?",
"RemoveComponentDialogCloseNote": "您确定要删除此组件吗?此操作无法撤销",
"Grouping": "分组",
"Ordering": "排序",
"CompletedIssues": "已完成问题",
"NoGrouping": "无分组",
"NoAssignee": "无受理人",
"LastUpdated": "最后更新",
"DueDate": "截止日期",
"IssueStartDate": "开始日期",
"GanttDependency": "Dependency",
"GanttLag": "Lag",
"Manual": "手动",
"All": "全部",
"PastWeek": "过去一周",
"PastMonth": "过去一个月",
"CopyIssueUrl": "复制问题 URL 到剪贴板",
"CopyIssueId": "复制问题 ID 到剪贴板",
"CopyIssueBranch": "复制 Git 分支名称到剪贴板",
"CopyIssueTitle": "复制问题标题到剪贴板",
"AssetLabel": "资产",
"AddToComponent": "添加到组件…",
"MoveToComponent": "移动到组件…",
"NoComponent": "无组件",
"ComponentLeadTitle": "组件负责人",
"ComponentMembersTitle": "组件成员",
"ComponentLeadSearchPlaceholder": "设置组件负责人…",
"ComponentMembersSearchPlaceholder": "更改组件成员…",
"MoveToProject": "移动到项目",
"Duplicate": "复制",
"GotoIssues": "前往问题",
"GotoActive": "前往活跃问题",
"GotoBacklog": "前往积压",
"GotoComponents": "前往组件",
"GotoMyIssues": "前往我的问题",
"GotoTrackerApplication": "切换到追踪器应用",
"CreatedOne": "已创建",
"MoveIssues": "移动问题",
"MoveIssuesDescription": "选择要移动问题的项目",
"ManageAttributes": "管理属性",
"KeepOriginalAttributes": "保留原始属性",
"KeepOriginalAttributesTooltip": "原始问题状态和组件将在新项目中保留",
"SelectReplacement": "以下项目在新项目中不可用。请选择替换项。",
"MissingItem": "缺失项目",
"Replacement": "替换项",
"Original": "原始",
"OriginalDescription": "此部分的项目将在新项目中创建",
"Relations": "关系",
"RemoveRelation": "移除关系…",
"AddBlockedBy": "标记为被阻塞…",
"AddIsBlocking": "标记为阻塞…",
"AddRelatedIssue": "引用其他问题…",
"RelatedIssue": "相关问题 {id} - {title}",
"BlockedIssue": "被阻塞的问题 {id} - {title}",
"BlockingIssue": "阻塞的问题 {id} - {title}",
"BlockedBySearchPlaceholder": "搜索要标记为被阻塞的问题…",
"IsBlockingSearchPlaceholder": "搜索要标记为阻塞的问题…",
"RelatedIssueSearchPlaceholder": "搜索要引用的问题…",
"Blocks": "阻塞",
"Related": "相关",
"RelatedIssues": "相关问题",
"EditIssue": "编辑 {title}",
"EditWorkflowStatuses": "编辑问题状态",
"EditProject": "编辑项目",
"DeleteProject": "删除项目",
"ArchiveProjectName": "归档项目 {name}",
"ArchiveProjectConfirm": "您想要归档此项目吗?",
"DeleteProjectConfirm": "您想要删除此项目及所有问题吗?",
"ProjectHasIssues": "此项目中存在问题,您确定要归档吗?",
"ManageWorkflowStatuses": "管理项目类型",
"AddWorkflowStatus": "添加问题状态",
"EditWorkflowStatus": "编辑问题状态",
"DeleteWorkflowStatus": "删除问题状态",
"DeleteWorkflowStatusConfirm": "您想要删除“{status}”状态吗?",
"DeleteWorkflowStatusErrorDescription": "“{status}”状态有 {count, plural, =1 {1 个问题} other {# 个问题}} 分配。请选择一个状态进行移动",
"Save": "保存",
"IncludeItemsThatMatch": "包括符合条件的项目",
"AnyFilter": "任何过滤器",
"AllFilters": "所有过滤器",
"NoDescription": "无描述",
"SearchIssue": "搜索任务…",
"StatusHistory": "状态历史",
"NewSubIssue": "添加子问题…",
"AddLabel": "添加标签",
"DeleteIssue": "删除 {issueCount, plural, =1 {问题} other {# 个问题}}",
"DeleteIssueConfirm": "您想要删除 {issueCount, plural, =1 {问题} other {问题}}{subIssueCount, plural, =0 {?} =1 { 和子问题?} other { 和子问题?}}",
"Milestone": "里程碑",
"NoMilestone": "无里程碑",
"MoveToMilestone": "选择里程碑",
"Milestones": "里程碑",
"AllMilestones": "全部",
"PlannedMilestones": "已计划",
"ActiveMilestones": "活跃",
"ClosedMilestones": "已完成",
"AddToMilestone": "添加到里程碑",
"MilestoneNamePlaceholder": "里程碑名称",
"NewMilestone": "新里程碑",
"CreateMilestone": "创建",
"MoveAndDeleteMilestone": "将问题移动到 {newMilestone} 并删除 {deleteMilestone}",
"MoveAndDeleteMilestoneConfirm": "您想要删除里程碑并将问题移动到其他里程碑吗?",
"Estimation": "估算",
"ReportedTime": "花费时间",
"RemainingTime": "剩余时间",
"TimeSpendReports": "花费时间报告",
"TimeSpendReport": "时间",
"TimeSpendReportAdd": "添加时间报告",
"TimeSpendReportDate": "日期",
"TimeSpendReportValue": "花费时间",
"TimeSpendReportValueTooltip": "花费时间(小时)",
"TimeSpendReportDescription": "描述",
"TimeSpendDays": "{value} 天",
"TimeSpendHours": "{value} 小时",
"TimeSpendMinutes": "{value} 分钟",
"ChildEstimation": "子问题估算",
"ChildReportedTime": "子问题时间",
"CapacityValue": "共 {value} 天",
"NewRelatedIssue": "新相关问题",
"RelatedIssuesNotFound": "未找到相关问题",
"AddedReference": "添加了引用",
"AddedAsBlocked": "标记为被阻塞",
"AddedAsBlocking": "标记为阻塞",
"IssueTemplate": "模板",
"IssueTemplates": "模板",
"NewProcess": "新模板",
"SaveProcess": "保存模板",
"NoIssueTemplate": "无模板",
"TemplateReplace": "您想要应用新模板吗?",
"TemplateReplaceConfirm": "所有字段将被新模板值覆盖",
"Apply": "应用",
"CurrentWorkDay": "当前工作日",
"PreviousWorkDay": "前一个工作日",
"TimeReportDayTypeLabel": "选择时间报告日类型",
"DefaultAssignee": "默认问题受理人",
"SevenHoursLength": "七小时",
"EightHoursLength": "八小时",
"HourLabel": "小时",
"MinuteLabel": "分",
"Saved": "已保存...",
"CreatedIssue": "已创建问题",
"CreatedSubIssue": "已创建子问题",
"ChangeStatus": "更改状态",
"ConfigLabel": "追踪器",
"ConfigDescription": "扩展用于管理工作项并完成所有工作。",
"NoStatusFound": "未找到匹配的状态",
"CreateMissingStatus": "创建缺失的状态",
"UnsetParent": "父问题将被取消设置",
"AllProjects": "所有项目",
"IssueNotificationTitle": "{issueTitle}",
"IssueNotificationBody": "由 {senderName} 更新",
"IssueNotificationChanged": "{senderName} 更改了 {property}",
"IssueNotificationChangedProperty": "{senderName} 将 {property} 更改为 \"{newValue}\"",
"IssueNotificationMessage": "{senderName}{message}",
"PreviousAssigned": "以前分配的",
"IssueAssignedToYou": "分配给您",
"RelatedIssueTargetDescription": "相关问题项目目标用于类别或空间",
"MapRelatedIssues": "配置相关问题默认项目",
"DefaultIssueStatus": "默认问题状态",
"IssueStatus": "状态",
"Extensions": "扩展",
"UnsetParentIssue": "取消父问题",
"ForbidCreateProjectPermission": "禁止创建项目",
"ForbidCreateProjectPermissionDescription": "禁止用户创建新项目",
"AllowCreatingIssues": "允许创建问题",
"ModeSelectorDisabledByFilter": "状态由活动筛选器控制。移除状态筛选器以使用此快捷方式。",
"ShowQuickModeSelector": "快速筛选:全部 / 活跃 / 积压",
"SearchScopeLabel": "搜索范围…",
"SearchScopeTitle": "仅标题",
"SearchScopeTitleDescription": "标题 + 描述",
"SearchScopeAll": "标题 + 描述 + 评论",
"SearchHighlight": "高亮显示搜索匹配项",
"SearchEmptyTitle": "未找到与 \"{query}\" 匹配的问题",
"SearchEmptyActiveFilters": "活动筛选器:{filters}",
"SearchEmptyClearFilters": "不使用筛选器搜索",
"SearchEmptyAllProjects": "在所有项目中搜索"
},
"status": {}
}