add translation for all 9 search option files

This commit is contained in:
Nriver 2024-08-07 10:16:27 +08:00
parent 9453ec4e29
commit 40f74656f3
11 changed files with 233 additions and 94 deletions

View File

@ -2,6 +2,7 @@ import server from "../../services/server.js";
import ws from "../../services/ws.js";
import Component from "../../components/component.js";
import utils from "../../services/utils.js";
import { t } from "../../services/i18n.js"; // 新增的导入
export default class AbstractSearchOption extends Component {
constructor(attribute, note) {
@ -27,14 +28,14 @@ export default class AbstractSearchOption extends Component {
$rendered.find('.search-option-del')
.on('click', () => this.deleteOption())
.attr('title', 'Remove this search option');
.attr('title', t('abstract_search_option.remove_this_search_option')); // 使用 t 函数处理 i18n 字符串
utils.initHelpDropdown($rendered);
return $rendered;
}
catch (e) {
logError(`Failed rendering search option: ${JSON.stringify(this.attribute.dto)} with error: ${e.message} ${e.stack}`);
logError(t('abstract_search_option.failed_rendering', { dto: JSON.stringify(this.attribute.dto), error: e.message, stack: e.stack })); // 使用 t 函数处理 i18n 字符串
return null;
}
}

View File

@ -1,46 +1,47 @@
import AbstractSearchOption from "./abstract_search_option.js";
import noteAutocompleteService from "../../services/note_autocomplete.js";
import { t } from "../../services/i18n.js";
const TPL = `
<tr>
<td colspan="2">
<div style="display: flex; align-items: center;">
<div style="margin-right: 10px">Ancestor:</div>
<div style="margin-right: 10px">${t('ancestor.label')}:</div>
<div class="input-group" style="flex-shrink: 2">
<input class="ancestor form-control" placeholder="search for note by its name">
<input class="ancestor form-control" placeholder="${t('ancestor.placeholder')}">
</div>
<div style="margin-left: 10px; margin-right: 10px">depth:</div>
<div style="margin-left: 10px; margin-right: 10px">${t('ancestor.depth_label')}:</div>
<select name="depth" class="form-control d-inline ancestor-depth" style="flex-shrink: 3">
<option value="">doesn't matter</option>
<option value="eq1">is exactly 1 (direct children)</option>
<option value="eq2">is exactly 2</option>
<option value="eq3">is exactly 3</option>
<option value="eq4">is exactly 4</option>
<option value="eq5">is exactly 5</option>
<option value="eq6">is exactly 6</option>
<option value="eq7">is exactly 7</option>
<option value="eq8">is exactly 8</option>
<option value="eq9">is exactly 9</option>
<option value="gt0">is greater than 0</option>
<option value="gt1">is greater than 1</option>
<option value="gt2">is greater than 2</option>
<option value="gt3">is greater than 3</option>
<option value="gt4">is greater than 4</option>
<option value="gt5">is greater than 5</option>
<option value="gt6">is greater than 6</option>
<option value="gt7">is greater than 7</option>
<option value="gt8">is greater than 8</option>
<option value="gt9">is greater than 9</option>
<option value="lt2">is less than 2</option>
<option value="lt3">is less than 3</option>
<option value="lt4">is less than 4</option>
<option value="lt5">is less than 5</option>
<option value="lt6">is less than 6</option>
<option value="lt7">is less than 7</option>
<option value="lt8">is less than 8</option>
<option value="lt9">is less than 9</option>
<option value="">${t('ancestor.depth_doesnt_matter')}</option>
<option value="eq1">${t('ancestor.depth_eq', {count: 1})} (${t('ancestor.direct_children')})</option>
<option value="eq2">${t('ancestor.depth_eq', {count: 2})}</option>
<option value="eq3">${t('ancestor.depth_eq', {count: 3})}</option>
<option value="eq4">${t('ancestor.depth_eq', {count: 4})}</option>
<option value="eq5">${t('ancestor.depth_eq', {count: 5})}</option>
<option value="eq6">${t('ancestor.depth_eq', {count: 6})}</option>
<option value="eq7">${t('ancestor.depth_eq', {count: 7})}</option>
<option value="eq8">${t('ancestor.depth_eq', {count: 8})}</option>
<option value="eq9">${t('ancestor.depth_eq', {count: 9})}</option>
<option value="gt0">${t('ancestor.depth_gt', {count: 0})}</option>
<option value="gt1">${t('ancestor.depth_gt', {count: 1})}</option>
<option value="gt2">${t('ancestor.depth_gt', {count: 2})}</option>
<option value="gt3">${t('ancestor.depth_gt', {count: 3})}</option>
<option value="gt4">${t('ancestor.depth_gt', {count: 4})}</option>
<option value="gt5">${t('ancestor.depth_gt', {count: 5})}</option>
<option value="gt6">${t('ancestor.depth_gt', {count: 6})}</option>
<option value="gt7">${t('ancestor.depth_gt', {count: 7})}</option>
<option value="gt8">${t('ancestor.depth_gt', {count: 8})}</option>
<option value="gt9">${t('ancestor.depth_gt', {count: 9})}</option>
<option value="lt2">${t('ancestor.depth_lt', {count: 2})}</option>
<option value="lt3">${t('ancestor.depth_lt', {count: 3})}</option>
<option value="lt4">${t('ancestor.depth_lt', {count: 4})}</option>
<option value="lt5">${t('ancestor.depth_lt', {count: 5})}</option>
<option value="lt6">${t('ancestor.depth_lt', {count: 6})}</option>
<option value="lt7">${t('ancestor.depth_lt', {count: 7})}</option>
<option value="lt8">${t('ancestor.depth_lt', {count: 8})}</option>
<option value="lt9">${t('ancestor.depth_lt', {count: 9})}</option>
</select>
</div>
</td>

View File

@ -1,22 +1,20 @@
import AbstractSearchOption from "./abstract_search_option.js";
import { t } from "../../services/i18n.js";
const TPL = `
<tr data-search-option-conf="debug">
<td colSpan="2">
<span class="bx bx-bug"></span>
Debug
${t("debug.debug")}
</td>
<td class="button-column">
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
<p>Debug will print extra debugging information into the console to aid in debugging complex queries.</p>
<p>To access the debug information, execute query and click on "Show backend log" in top left corner.</p>
<p>${t("debug.debug_info")}</p>
<p>${t("debug.access_info")}</p>
</div>
</div>
<span class="bx bx-x icon-action search-option-del"></span>
</td>
</tr>`;

View File

@ -1,20 +1,19 @@
import AbstractSearchOption from "./abstract_search_option.js";
import { t } from "../../services/i18n.js";
const TPL = `
<tr data-search-option-conf="fastSearch">
<td colSpan="2">
<span class="bx bx-run"></span>
Fast search
${t('fast_search.fast_search')}
</td>
<td class="button-column">
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
Fast search option disables full text search of note contents which might speed up searching in large databases.
${t('fast_search.description')}
</div>
</div>
<span class="bx bx-x icon-action search-option-del"></span>
</td>
</tr>`;

View File

@ -1,11 +1,11 @@
import AbstractSearchOption from "./abstract_search_option.js";
import { t } from "../../services/i18n.js";
const TPL = `
<tr data-search-option-conf="includeArchivedNotes">
<td colspan="2">
<span class="bx bx-archive"></span>
Include archived notes
${t('include_archived_notes.include_archived_notes')}
</td>
<td class="button-column">
<span class="bx bx-x icon-action search-option-del"></span>

View File

@ -1,11 +1,11 @@
import AbstractSearchOption from "./abstract_search_option.js";
import { t } from "../../services/i18n.js";
const TPL = `
<tr data-search-option-conf="limit">
<td class="title-column">
<span class="bx bx-stop"></span>
Limit
${t('limit.limit')}
</td>
<td>
<input name="limit" class="form-control" type="number" min="1" step="1" />
@ -14,7 +14,7 @@ const TPL = `
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
Take only first X specified results.
${t('limit.take_first_x_results')}
</div>
</div>

View File

@ -1,33 +1,33 @@
import AbstractSearchOption from "./abstract_search_option.js";
import { t } from "../../services/i18n.js";
const TPL = `
<tr data-search-option-conf="orderBy">
<td class="title-column">
<span class="bx bx-arrow-from-top"></span>
Order by
${t('order_by.order_by')}
</td>
<td>
<select name="orderBy" class="form-control w-auto d-inline">
<option value="relevancy">Relevancy (default)</option>
<option value="title">Title</option>
<option value="dateCreated">Date created</option>
<option value="dateModified">Date of last modification</option>
<option value="contentSize">Note content size</option>
<option value="contentAndAttachmentsSize">Note content size including attachments</option>
<option value="contentAndAttachmentsAndRevisionsSize">Note content size including attachments and revisions</option>
<option value="revisionCount">Number of revisions</option>
<option value="childrenCount">Number of children notes</option>
<option value="parentCount">Number of clones</option>
<option value="ownedLabelCount">Number of labels</option>
<option value="ownedRelationCount">Number of relations</option>
<option value="targetRelationCount">Number of relations targeting the note</option>
<option value="random">Random order</option>
<option value="relevancy">${t('order_by.relevancy')}</option>
<option value="title">${t('order_by.title')}</option>
<option value="dateCreated">${t('order_by.date_created')}</option>
<option value="dateModified">${t('order_by.date_modified')}</option>
<option value="contentSize">${t('order_by.content_size')}</option>
<option value="contentAndAttachmentsSize">${t('order_by.content_and_attachments_size')}</option>
<option value="contentAndAttachmentsAndRevisionsSize">${t('order_by.content_and_attachments_and_revisions_size')}</option>
<option value="revisionCount">${t('order_by.revision_count')}</option>
<option value="childrenCount">${t('order_by.children_count')}</option>
<option value="parentCount">${t('order_by.parent_count')}</option>
<option value="ownedLabelCount">${t('order_by.owned_label_count')}</option>
<option value="ownedRelationCount">${t('order_by.owned_relation_count')}</option>
<option value="targetRelationCount">${t('order_by.target_relation_count')}</option>
<option value="random">${t('order_by.random')}</option>
</select>
<select name="orderDirection" class="form-control w-auto d-inline">
<option value="asc">Ascending (default)</option>
<option value="desc">Descending</option>
<option value="asc">${t('order_by.asc')}</option>
<option value="desc">${t('order_by.desc')}</option>
</select>
</td>
<td class="button-column">

View File

@ -1,37 +1,30 @@
import AbstractSearchOption from "./abstract_search_option.js";
import noteAutocompleteService from "../../services/note_autocomplete.js";
import { t } from "../../services/i18n.js";
const TPL = `
<tr>
<td class="title-column">
Search script:
${t('search_script.title')}
</td>
<td>
<div class="input-group">
<input class="search-script form-control" placeholder="search for note by its name">
<input class="search-script form-control" placeholder="${t('search_script.placeholder')}">
</div>
</td>
<td class="button-column">
<td class="button-column">
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
<p>Search script allows to define search results by running a script. This provides maximal flexibility when standard search doesn't suffice.</p>
<p>${t('search_script.description1')}</p>
<p>Search script must be of type "code" and subtype "JavaScript backend". The script receives needs to return an array of noteIds or notes.</p>
<p>${t('search_script.description2')}</p>
<p>See this example:</p>
<p>${t('search_script.example_title')}</p>
<pre>
// 1. prefiltering using standard search
const candidateNotes = api.searchForNotes("#journal");
<pre>${t('search_script.example_code')}</pre>
// 2. applying custom search criteria
const matchedNotes = candidateNotes
.filter(note => note.title.match(/[0-9]{1,2}\. ?[0-9]{1,2}\. ?[0-9]{4}\/));
return matchedNotes;</pre>
<p>Note that search script and search string can't be combined with each other.</p>
<p>${t('search_script.note')}</p>
</div>
</div>

View File

@ -3,27 +3,28 @@ import SpacedUpdate from "../../services/spaced_update.js";
import server from "../../services/server.js";
import shortcutService from "../../services/shortcuts.js";
import appContext from "../../components/app_context.js";
import { t } from "../../services/i18n.js";
const TPL = `
<tr>
<td class="title-column">Search string:</td>
<td class="title-column">${t('search_string.title_column')}</td>
<td>
<textarea class="form-control search-string" placeholder="fulltext keywords, #tag = value ..."></textarea>
<textarea class="form-control search-string" placeholder="${t('search_string.placeholder')}"></textarea>
</td>
<td class="button-column">
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
<strong>Search syntax</strong> - also see <button class="btn btn-sm" type="button" data-help-page="Search">complete help on search syntax</button>
<strong>${t('search_string.search_syntax')}</strong> - ${t('search_string.also_see')} <button class="btn btn-sm" type="button" data-help-page="Search">${t('search_string.complete_help')}</button>
<p>
<ul>
<li>Just enter any text for full text search</li>
<li><code>#abc</code> - returns notes with label abc</li>
<li><code>#year = 2019</code> - matches notes with label <code>year</code> having value <code>2019</code></li>
<li><code>#rock #pop</code> - matches notes which have both <code>rock</code> and <code>pop</code> labels</li>
<li><code>#rock or #pop</code> - only one of the labels must be present</li>
<li><code>#year &lt;= 2000</code> - numerical comparison (also &gt;, &gt;=, &lt;).</li>
<li><code>note.dateCreated >= MONTH-1</code> - notes created in the last month</li>
<li>${t('search_string.full_text_search')}</li>
<li><code>#abc</code> - ${t('search_string.label_abc')}</li>
<li><code>#year = 2019</code> - ${t('search_string.label_year')}</li>
<li><code>#rock #pop</code> - ${t('search_string.label_rock_pop')}</li>
<li><code>#rock or #pop</code> - ${t('search_string.label_rock_or_pop')}</li>
<li><code>#year &lt;= 2000</code> - ${t('search_string.label_year_comparison')}</li>
<li><code>note.dateCreated >= MONTH-1</code> - ${t('search_string.label_date_created')}</li>
</ul>
</p>
</div>
@ -76,7 +77,7 @@ export default class SearchString extends AbstractSearchOption {
showSearchErrorEvent({error}) {
this.$searchString.tooltip({
trigger: 'manual',
title: `Search error: ${error}`,
title: `${t('search_string.error', {error})}`,
placement: 'bottom'
});

View File

@ -712,7 +712,7 @@
"modified": "修改时间",
"type": "类型",
"note_size": "笔记大小",
"note_size_info": "笔记大小提供了该笔记存储需求的粗略估计。它考虑了笔记的内容及其笔记修订的内容。",
"note_size_info": "笔记大小提供了该笔记存储需求的粗略估计。它考虑了笔记的内容及其笔记历史的内容。",
"calculate": "计算",
"subtree_size": "(子树大小: {{size}}, 共计 {{count}} 个笔记)",
"title": "笔记信息"
@ -780,5 +780,78 @@
"similar_notes": {
"title": "相似笔记",
"no_similar_notes_found": "未找到相似的笔记。"
},
"abstract_search_option": {
"remove_this_search_option": "删除此搜索选项",
"failed_rendering": "渲染搜索选项失败:{{dto}},错误信息:{{error}},堆栈:{{stack}}"
},
"ancestor": {
"label": "祖先",
"placeholder": "按名称搜索笔记",
"depth_label": "深度",
"depth_doesnt_matter": "任意",
"depth_eq": "正好是 {{count}}",
"direct_children": "直接子代",
"depth_gt": "大于 {{count}}",
"depth_lt": "小于 {{count}}"
},
"debug": {
"debug": "调试",
"debug_info": "调试将打印额外的调试信息到控制台,以帮助调试复杂的查询。",
"access_info": "要访问调试信息,请执行查询并点击左上角的“显示后端日志”。"
},
"fast_search": {
"fast_search": "快速搜索",
"description": "快速搜索选项禁用笔记内容的全文搜索,这可能会加快在大型数据库中的搜索速度。"
},
"include_archived_notes": {
"include_archived_notes": "包括已归档的笔记"
},
"limit": {
"limit": "限制",
"take_first_x_results": "仅取前X个指定结果。"
},
"order_by": {
"order_by": "排序依据",
"relevancy": "相关性(默认)",
"title": "标题",
"date_created": "创建日期",
"date_modified": "最后修改日期",
"content_size": "笔记内容大小",
"content_and_attachments_size": "笔记内容大小(包括附件)",
"content_and_attachments_and_revisions_size": "笔记内容大小(包括附件和笔记历史)",
"revision_count": "历史数量",
"children_count": "子笔记数量",
"parent_count": "克隆数量",
"owned_label_count": "标签数量",
"owned_relation_count": "关系数量",
"target_relation_count": "指向笔记的关系数量",
"random": "随机顺序",
"asc": "升序(默认)",
"desc": "降序"
},
"search_script": {
"title": "搜索脚本:",
"placeholder": "按名称搜索笔记",
"description1": "搜索脚本允许通过运行脚本来定义搜索结果。这在标准搜索不足时提供了最大的灵活性。",
"description2": "搜索脚本必须是类型为\"代码\"和子类型为\"JavaScript后端\"。脚本需要返回一个noteIds或notes数组。",
"example_title": "请看这个例子:",
"example_code": "// 1. 使用标准搜索进行预过滤\nconst candidateNotes = api.searchForNotes(\"#journal\"); \n\n// 2. 应用自定义搜索条件\nconst matchedNotes = candidateNotes\n .filter(note => note.title.match(/[0-9]{1,2}\\. ?[0-9]{1,2}\\. ?[0-9]{4}/));\n\nreturn matchedNotes;",
"note": "注意,搜索脚本和搜索字符串不能相互结合使用。"
},
"search_string": {
"title_column": "搜索字符串:",
"placeholder": "全文关键词,#标签 = 值 ...",
"search_syntax": "搜索语法",
"also_see": "另见",
"complete_help": "完整的搜索语法帮助",
"full_text_search": "只需输入任何文本进行全文搜索",
"label_abc": "返回带有标签abc的笔记",
"label_year": "匹配带有标签年份且值为2019的笔记",
"label_rock_pop": "匹配同时具有rock和pop标签的笔记",
"label_rock_or_pop": "只需一个标签存在即可",
"label_year_comparison": "数字比较(也包括>>=<)。",
"label_date_created": "上个月创建的笔记",
"error": "搜索错误:{{error}}"
}
}

View File

@ -781,5 +781,78 @@
"similar_notes": {
"title": "Similar Notes",
"no_similar_notes_found": "No similar notes found."
},
"abstract_search_option": {
"remove_this_search_option": "Remove this search option",
"failed_rendering": "Failed rendering search option: {{dto}} with error: {{error}} {{stack}}"
},
"ancestor": {
"label": "Ancestor",
"placeholder": "search for note by its name",
"depth_label": "depth",
"depth_doesnt_matter": "doesn't matter",
"depth_eq": "is exactly {{count}}",
"direct_children": "direct children",
"depth_gt": "is greater than {{count}}",
"depth_lt": "is less than {{count}}"
},
"debug": {
"debug": "Debug",
"debug_info": "Debug will print extra debugging information into the console to aid in debugging complex queries.",
"access_info": "To access the debug information, execute query and click on \"Show backend log\" in top left corner."
},
"fast_search": {
"fast_search": "Fast search",
"description": "Fast search option disables full text search of note contents which might speed up searching in large databases."
},
"include_archived_notes": {
"include_archived_notes": "Include archived notes"
},
"limit": {
"limit": "Limit",
"take_first_x_results": "Take only first X specified results."
},
"order_by": {
"order_by": "Order by",
"relevancy": "Relevancy (default)",
"title": "Title",
"date_created": "Date created",
"date_modified": "Date of last modification",
"content_size": "Note content size",
"content_and_attachments_size": "Note content size including attachments",
"content_and_attachments_and_revisions_size": "Note content size including attachments and revisions",
"revision_count": "Number of revisions",
"children_count": "Number of children notes",
"parent_count": "Number of clones",
"owned_label_count": "Number of labels",
"owned_relation_count": "Number of relations",
"target_relation_count": "Number of relations targeting the note",
"random": "Random order",
"asc": "Ascending (default)",
"desc": "Descending"
},
"search_script": {
"title": "Search script:",
"placeholder": "search for note by its name",
"description1": "Search script allows to define search results by running a script. This provides maximal flexibility when standard search doesn't suffice.",
"description2": "Search script must be of type \"code\" and subtype \"JavaScript backend\". The script needs to return an array of noteIds or notes.",
"example_title": "See this example:",
"example_code": "// 1. prefiltering using standard search\nconst candidateNotes = api.searchForNotes(\"#journal\"); \n\n// 2. applying custom search criteria\nconst matchedNotes = candidateNotes\n .filter(note => note.title.match(/[0-9]{1,2}\\. ?[0-9]{1,2}\\. ?[0-9]{4}/));\n\nreturn matchedNotes;",
"note": "Note that search script and search string can't be combined with each other."
},
"search_string": {
"title_column": "Search string:",
"placeholder": "fulltext keywords, #tag = value ...",
"search_syntax": "Search syntax",
"also_see": "also see",
"complete_help": "complete help on search syntax",
"full_text_search": "Just enter any text for full text search",
"label_abc": "returns notes with label abc",
"label_year": "matches notes with label year having value 2019",
"label_rock_pop": "matches notes which have both rock and pop labels",
"label_rock_or_pop": "only one of the labels must be present",
"label_year_comparison": "numerical comparison (also >, >=, <).",
"label_date_created": "notes created in the last month",
"error": "Search error: {{error}}"
}
}