There are no tokens yet. Click on the button above to create one.
+
${t("etapi.no_tokens_yet")}
-
Token name
-
Created
-
Actions
+
${t("etapi.token_name")}
+
${t("etapi.created")}
+
${t("etapi.actions")}
@@ -52,21 +53,21 @@ export default class EtapiOptions extends OptionsWidget {
this.$widget.find(".create-etapi-token").on("click", async () => {
const tokenName = await dialogService.prompt({
- title: "New ETAPI token",
- message: "Please enter new token's name",
- defaultValue: "new token"
+ title: t("etapi.new_token_title"),
+ message: t("etapi.new_token_message"),
+ defaultValue: t("etapi.default_token_name")
});
if (!tokenName.trim()) {
- toastService.showError("Token name can't be empty");
+ toastService.showError(t("etapi.error_empty_name"));
return;
}
const {authToken} = await server.post('etapi-tokens', {tokenName});
await dialogService.prompt({
- title: "ETAPI token created",
- message: 'Copy the created token into clipboard. Trilium stores the token hashed and this is the last time you see it.',
+ title: t("etapi.token_created_title"),
+ message: t("etapi.token_created_message"),
defaultValue: authToken
});
@@ -94,9 +95,9 @@ export default class EtapiOptions extends OptionsWidget {
.append($("
").text(token.name))
.append($("
").text(token.utcDateCreated))
.append($("
").append(
- $('')
+ $('')
.on("click", () => this.renameToken(token.etapiTokenId, token.name)),
- $('')
+ $('')
.on("click", () => this.deleteToken(token.etapiTokenId, token.name))
))
);
@@ -105,8 +106,8 @@ export default class EtapiOptions extends OptionsWidget {
async renameToken(etapiTokenId, oldName) {
const tokenName = await dialogService.prompt({
- title: "Rename token",
- message: "Please enter new token's name",
+ title: t("etapi.rename_token_title"),
+ message: t("etapi.rename_token_message"),
defaultValue: oldName
});
@@ -120,7 +121,7 @@ export default class EtapiOptions extends OptionsWidget {
}
async deleteToken(etapiTokenId, name) {
- if (!await dialogService.confirm(`Are you sure you want to delete ETAPI token "${name}"?`)) {
+ if (!await dialogService.confirm(t("etapi.delete_token_confirmation", { name }))) {
return;
}
diff --git a/src/public/app/widgets/type_widgets/options/options_widget.js b/src/public/app/widgets/type_widgets/options/options_widget.js
index 3f1630870..bfbcb8657 100644
--- a/src/public/app/widgets/type_widgets/options/options_widget.js
+++ b/src/public/app/widgets/type_widgets/options/options_widget.js
@@ -1,3 +1,4 @@
+import { t } from "../../../services/i18n.js";
import server from "../../../services/server.js";
import toastService from "../../../services/toast.js";
import NoteContextAwareWidget from "../../note_context_aware_widget.js";
@@ -24,8 +25,8 @@ export default class OptionsWidget extends NoteContextAwareWidget {
showUpdateNotification() {
toastService.showPersistent({
id: "options-change-saved",
- title: "Options status",
- message: "Options change have been saved.",
+ title: t("options_widget.options_status"),
+ message: t("options_widget.options_change_saved"),
icon: "slider",
closeAfter: 2000
});
diff --git a/src/public/app/widgets/type_widgets/options/password.js b/src/public/app/widgets/type_widgets/options/password.js
index 7b42fb064..228e3ecd1 100644
--- a/src/public/app/widgets/type_widgets/options/password.js
+++ b/src/public/app/widgets/type_widgets/options/password.js
@@ -1,3 +1,4 @@
+import { t } from "../../../services/i18n.js";
import server from "../../../services/server.js";
import protectedSessionHolder from "../../../services/protected_session_holder.js";
import toastService from "../../../services/toast.js";
@@ -5,42 +6,39 @@ import OptionsWidget from "./options_widget.js";
const TPL = `
-
+
${t("password.heading")}
- Please take care to remember your new password. Password is used for logging into the web interface and
- to encrypt protected notes. If you forget your password, then all your protected notes are forever lost.
- In case you did forget your password, click here to reset it.
+ ${t("password.alert_message")} ${t("password.reset_link")}
-
Protected Session Timeout
+
${t("password.protected_session_timeout")}
-
Protected session timeout is a time period after which the protected session is wiped from
- the browser's memory. This is measured from the last interaction with protected notes. See wiki for more info.
`;
@@ -58,13 +56,13 @@ export default class PasswordOptions extends OptionsWidget {
this.$resetPasswordButton = this.$widget.find(".reset-password-button");
this.$resetPasswordButton.on("click", async () => {
- if (confirm("By resetting the password you will forever lose access to all your existing protected notes. Do you really want to reset the password?")) {
+ if (confirm(t("password.reset_confirmation"))) {
await server.post("password/reset?really=yesIReallyWantToResetPasswordAndLoseAccessToMyProtectedNotes");
const options = await server.get('options');
this.optionsLoaded(options);
- toastService.showError("Password has been reset. Please set new password");
+ toastService.showError(t("password.reset_success_message"));
}
});
@@ -79,8 +77,8 @@ export default class PasswordOptions extends OptionsWidget {
const isPasswordSet = options.isPasswordSet === 'true';
this.$widget.find(".old-password-form-group").toggle(isPasswordSet);
- this.$passwordHeading.text(isPasswordSet ? 'Change Password' : 'Set Password');
- this.$savePasswordButton.text(isPasswordSet ? 'Change Password' : 'Set Password');
+ this.$passwordHeading.text(isPasswordSet ? t("password.change_password_heading") : t("password.set_password_heading"));
+ this.$savePasswordButton.text(isPasswordSet ? t("password.change_password") : t("password.set_password"));
this.$protectedSessionTimeout.val(options.protectedSessionTimeout);
}
@@ -94,7 +92,7 @@ export default class PasswordOptions extends OptionsWidget {
this.$newPassword2.val('');
if (newPassword1 !== newPassword2) {
- toastService.showError("New passwords are not the same.");
+ toastService.showError(t("password.password_mismatch"));
return false;
}
@@ -103,7 +101,7 @@ export default class PasswordOptions extends OptionsWidget {
'new_password': newPassword1
}).then(result => {
if (result.success) {
- toastService.showError("Password has been changed. Trilium will be reloaded after you press OK.");
+ toastService.showError(t("password.password_changed_success"));
// password changed so current protected session is invalid and needs to be cleared
protectedSessionHolder.resetProtectedSession();
diff --git a/src/public/translations/cn/translation.json b/src/public/translations/cn/translation.json
index 35acbd982..ba35e9a8f 100644
--- a/src/public/translations/cn/translation.json
+++ b/src/public/translations/cn/translation.json
@@ -1128,8 +1128,58 @@
"backup_recommendation": "建议打开备份功能,但这可能会使大型数据库和/或慢速存储设备的应用程序启动变慢。",
"backup_now": "立即备份",
"backup_database_now": "立即备份数据库",
- "existing_backups": "已有备份",
+ "existing_backups": "现有备份",
"database_backed_up_to": "数据库已备份到",
"no_backup_yet": "尚无备份"
+ },
+ "etapi": {
+ "title": "ETAPI",
+ "description": "ETAPI 是一个 REST API,用于以编程方式访问 Trilium 实例,而无需 UI。",
+ "see_more": "更多详情见",
+ "wiki": "维基",
+ "and": "和",
+ "openapi_spec": "ETAPI OpenAPI 规范",
+ "create_token": "创建新的 ETAPI 令牌",
+ "existing_tokens": "现有令牌",
+ "no_tokens_yet": "目前还没有令牌。点击上面的按钮创建一个。",
+ "token_name": "令牌名称",
+ "created": "创建时间",
+ "actions": "操作",
+ "new_token_title": "新 ETAPI 令牌",
+ "new_token_message": "请输入新的令牌名称",
+ "default_token_name": "新令牌",
+ "error_empty_name": "令牌名称不能为空",
+ "token_created_title": "ETAPI 令牌已创建",
+ "token_created_message": "将创建的令牌复制到剪贴板。Trilium 存储了令牌的哈希值,这是你最后一次看到它。",
+ "rename_token": "重命名此令牌",
+ "delete_token": "删除/停用此令牌",
+ "rename_token_title": "重命名令牌",
+ "rename_token_message": "请输入新的令牌名称",
+ "delete_token_confirmation": "你确定要删除 ETAPI 令牌 \"{{name}}\" 吗?"
+ },
+ "options_widget": {
+ "options_status": "选项状态",
+ "options_change_saved": "选项更改已保存。"
+ },
+ "password": {
+ "heading": "密码",
+ "alert_message": "请务必记住您的新密码。密码用于登录 Web 界面和加密保护的笔记。如果您忘记了密码,所有保护的笔记将永久丢失。",
+ "reset_link": "点击这里重置。",
+ "old_password": "旧密码",
+ "new_password": "新密码",
+ "new_password_confirmation": "新密码确认",
+ "change_password": "更改密码",
+ "protected_session_timeout": "保护会话超时",
+ "protected_session_timeout_description": "保护会话超时是一个时间段,超时后保护会话会从浏览器内存中清除。这是从最后一次与保护笔记的交互开始计时的。更多信息请见",
+ "wiki": "维基",
+ "for_more_info": "更多信息。",
+ "protected_session_timeout_label": "保护会话超时(秒)",
+ "reset_confirmation": "重置密码将永久丧失对所有现受保护笔记的访问。您真的要重置密码吗?",
+ "reset_success_message": "密码已重置。请设置新密码",
+ "change_password_heading": "更改密码",
+ "set_password_heading": "设置密码",
+ "set_password": "设置密码",
+ "password_mismatch": "新密码不一致。",
+ "password_changed_success": "密码已更改。按 OK 后 Trilium 将重新加载。"
}
}
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index ced29aa37..f36f6d93a 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1132,5 +1132,55 @@
"existing_backups": "Existing backups",
"database_backed_up_to": "Database has been backed up to",
"no_backup_yet": "no backup yet"
+ },
+ "etapi": {
+ "title": "ETAPI",
+ "description": "ETAPI is a REST API used to access Trilium instance programmatically, without UI.",
+ "see_more": "See more details on",
+ "wiki": "wiki",
+ "and": "and",
+ "openapi_spec": "ETAPI OpenAPI spec",
+ "create_token": "Create new ETAPI token",
+ "existing_tokens": "Existing tokens",
+ "no_tokens_yet": "There are no tokens yet. Click on the button above to create one.",
+ "token_name": "Token name",
+ "created": "Created",
+ "actions": "Actions",
+ "new_token_title": "New ETAPI token",
+ "new_token_message": "Please enter new token's name",
+ "default_token_name": "new token",
+ "error_empty_name": "Token name can't be empty",
+ "token_created_title": "ETAPI token created",
+ "token_created_message": "Copy the created token into clipboard. Trilium stores the token hashed and this is the last time you see it.",
+ "rename_token": "Rename this token",
+ "delete_token": "Delete / deactivate this token",
+ "rename_token_title": "Rename token",
+ "rename_token_message": "Please enter new token's name",
+ "delete_token_confirmation": "Are you sure you want to delete ETAPI token \"{{name}}\"?"
+ },
+ "options_widget": {
+ "options_status": "Options status",
+ "options_change_saved": "Options change have been saved."
+ },
+ "password": {
+ "heading": "Password",
+ "alert_message": "Please take care to remember your new password. Password is used for logging into the web interface and to encrypt protected notes. If you forget your password, then all your protected notes are forever lost.",
+ "reset_link": "click here to reset it.",
+ "old_password": "Old password",
+ "new_password": "New password",
+ "new_password_confirmation": "New password confirmation",
+ "change_password": "Change password",
+ "protected_session_timeout": "Protected Session Timeout",
+ "protected_session_timeout_description": "Protected session timeout is a time period after which the protected session is wiped from the browser's memory. This is measured from the last interaction with protected notes. See",
+ "wiki": "wiki",
+ "for_more_info": "for more info.",
+ "protected_session_timeout_label": "Protected session timeout (in seconds)",
+ "reset_confirmation": "By resetting the password you will forever lose access to all your existing protected notes. Do you really want to reset the password?",
+ "reset_success_message": "Password has been reset. Please set new password",
+ "change_password_heading": "Change Password",
+ "set_password_heading": "Set Password",
+ "set_password": "Set Password",
+ "password_mismatch": "New passwords are not the same.",
+ "password_changed_success": "Password has been changed. Trilium will be reloaded after you press OK."
}
}
From 78e908c761e8e5b3e8dd1b11cd2ff540b41891c7 Mon Sep 17 00:00:00 2001
From: Nriver <6752679+Nriver@users.noreply.github.com>
Date: Wed, 14 Aug 2024 17:12:33 +0800
Subject: [PATCH 03/10] add translation for shortcuts.js
---
.../widgets/type_widgets/options/shortcuts.js | 41 ++++++++++---------
src/public/translations/cn/translation.json | 13 ++++++
src/public/translations/en/translation.json | 13 ++++++
3 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/src/public/app/widgets/type_widgets/options/shortcuts.js b/src/public/app/widgets/type_widgets/options/shortcuts.js
index 9430ba85f..19a6272c1 100644
--- a/src/public/app/widgets/type_widgets/options/shortcuts.js
+++ b/src/public/app/widgets/type_widgets/options/shortcuts.js
@@ -2,6 +2,7 @@ import server from "../../../services/server.js";
import utils from "../../../services/utils.js";
import dialogService from "../../../services/dialog.js";
import OptionsWidget from "./options_widget.js";
+import { t } from "../../../services/i18n.js";
const TPL = `
@@ -25,25 +26,25 @@ const TPL = `
}
-
Keyboard Shortcuts
+
${t('shortcuts.keyboard_shortcuts')}
- Multiple shortcuts for the same action can be separated by comma.
- See Electron documentation for available modifiers and key codes.
+ ${t('shortcuts.multiple_shortcuts')}
+ ${t('shortcuts.electron_documentation')}
").text(action.defaultShortcuts.join(", ")))
@@ -101,10 +102,10 @@ export default class KeyboardShortcutsOptions extends OptionsWidget {
const $input = this.$widget.find(e.target);
const actionName = $input.attr('data-keyboard-action-name');
const shortcuts = $input.val()
- .replace('+,', "+Comma")
- .split(",")
- .map(shortcut => shortcut.replace("+Comma", "+,"))
- .filter(shortcut => !!shortcut);
+ .replace('+,', "+Comma")
+ .split(",")
+ .map(shortcut => shortcut.replace("+Comma", "+,"))
+ .filter(shortcut => !!shortcut);
const optionName = `keyboardShortcuts${actionName.substr(0, 1).toUpperCase()}${actionName.substr(1)}`;
@@ -112,7 +113,7 @@ export default class KeyboardShortcutsOptions extends OptionsWidget {
});
this.$widget.find(".options-keyboard-shortcuts-set-all-to-default").on('click', async () => {
- if (!await dialogService.confirm("Do you really want to reset all keyboard shortcuts to the default?")) {
+ if (!await dialogService.confirm(t('shortcuts.confirm_reset'))) {
return;
}
@@ -152,7 +153,7 @@ export default class KeyboardShortcutsOptions extends OptionsWidget {
return;
}
- this.$widget.find(el).toggle(!!( // !! to avoid toggle overloads with different behavior
+ this.$widget.find(el).toggle(!!(
action.actionName.toLowerCase().includes(filter)
|| action.defaultShortcuts.some(shortcut => shortcut.toLowerCase().includes(filter))
|| action.effectiveShortcuts.some(shortcut => shortcut.toLowerCase().includes(filter))
diff --git a/src/public/translations/cn/translation.json b/src/public/translations/cn/translation.json
index ba35e9a8f..2efb60d67 100644
--- a/src/public/translations/cn/translation.json
+++ b/src/public/translations/cn/translation.json
@@ -1181,5 +1181,18 @@
"set_password": "设置密码",
"password_mismatch": "新密码不一致。",
"password_changed_success": "密码已更改。按 OK 后 Trilium 将重新加载。"
+ },
+ "shortcuts": {
+ "keyboard_shortcuts": "快捷键",
+ "multiple_shortcuts": "同一操作的多个快捷键可以用逗号分隔。",
+ "electron_documentation": "请参阅 Electron文档,了解可用的修饰符和键码。",
+ "type_text_to_filter": "输入文字以过滤快捷键...",
+ "action_name": "操作名称",
+ "shortcuts": "快捷键",
+ "default_shortcuts": "默认快捷键",
+ "description": "描述",
+ "reload_app": "重新加载应用以应用更改",
+ "set_all_to_default": "将所有快捷键重置为默认值",
+ "confirm_reset": "您确定要将所有键盘快捷键重置为默认值吗?"
}
}
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index f36f6d93a..1fc78b79e 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1182,5 +1182,18 @@
"set_password": "Set Password",
"password_mismatch": "New passwords are not the same.",
"password_changed_success": "Password has been changed. Trilium will be reloaded after you press OK."
+ },
+ "shortcuts": {
+ "keyboard_shortcuts": "Keyboard Shortcuts",
+ "multiple_shortcuts": "Multiple shortcuts for the same action can be separated by comma.",
+ "electron_documentation": "See Electron documentation for available modifiers and key codes.",
+ "type_text_to_filter": "Type text to filter shortcuts...",
+ "action_name": "Action name",
+ "shortcuts": "Shortcuts",
+ "default_shortcuts": "Default shortcuts",
+ "description": "Description",
+ "reload_app": "Reload app to apply changes",
+ "set_all_to_default": "Set all shortcuts to the default",
+ "confirm_reset": "Do you really want to reset all keyboard shortcuts to the default?"
}
}
From 9210f915cac1185a41d5a87a55b43bd33c2d9711 Mon Sep 17 00:00:00 2001
From: Nriver <6752679+Nriver@users.noreply.github.com>
Date: Wed, 14 Aug 2024 17:14:07 +0800
Subject: [PATCH 04/10] fix text wrap for shortcuts.js
---
src/public/app/widgets/type_widgets/options/shortcuts.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/public/app/widgets/type_widgets/options/shortcuts.js b/src/public/app/widgets/type_widgets/options/shortcuts.js
index 19a6272c1..bbfa28933 100644
--- a/src/public/app/widgets/type_widgets/options/shortcuts.js
+++ b/src/public/app/widgets/type_widgets/options/shortcuts.js
@@ -40,7 +40,7 @@ const TPL = `
-
+
${t('shortcuts.action_name')}
${t('shortcuts.shortcuts')}
${t('shortcuts.default_shortcuts')}
From a78859fc2aaffa0d1a3e2a71330951625b6d9b22 Mon Sep 17 00:00:00 2001
From: Nriver <6752679+Nriver@users.noreply.github.com>
Date: Thu, 15 Aug 2024 11:26:51 +0800
Subject: [PATCH 05/10] add translation for the last 2 option files
---
.../type_widgets/options/spellcheck.js | 15 +++++-----
.../app/widgets/type_widgets/options/sync.js | 28 +++++++++----------
src/public/translations/cn/translation.json | 24 ++++++++++++++++
src/public/translations/en/translation.json | 24 ++++++++++++++++
4 files changed, 70 insertions(+), 21 deletions(-)
diff --git a/src/public/app/widgets/type_widgets/options/spellcheck.js b/src/public/app/widgets/type_widgets/options/spellcheck.js
index 1f714ca0b..df2daa8e4 100644
--- a/src/public/app/widgets/type_widgets/options/spellcheck.js
+++ b/src/public/app/widgets/type_widgets/options/spellcheck.js
@@ -1,27 +1,28 @@
import utils from "../../../services/utils.js";
import OptionsWidget from "./options_widget.js";
+import { t } from "../../../services/i18n.js";
const TPL = `
-
Spell Check
+
${t('spellcheck.title')}
-
These options apply only for desktop builds, browsers will use their own native spell check. App restart is required after change.
+
${t('spellcheck.description')}
-
-
+
+
-
Multiple languages can be separated by comma, e.g. en-US, de-DE, cs. Changes to the spell check options will take effect after application restart.
+
${t('spellcheck.multiple_languages_info')}
-
Available language codes:
+
${t('spellcheck.available_language_codes_label')}
`;
export default class SpellcheckOptions extends OptionsWidget {
diff --git a/src/public/app/widgets/type_widgets/options/sync.js b/src/public/app/widgets/type_widgets/options/sync.js
index bb8e3c9dd..0b5bebf9d 100644
--- a/src/public/app/widgets/type_widgets/options/sync.js
+++ b/src/public/app/widgets/type_widgets/options/sync.js
@@ -1,44 +1,45 @@
import server from "../../../services/server.js";
import toastService from "../../../services/toast.js";
import OptionsWidget from "./options_widget.js";
+import { t } from "../../../services/i18n.js";
const TPL = `
-
Sync Configuration
+
${t('sync_2.config_title')}
-
Sync Test
+
${t('sync_2.test_title')}
-
This will test the connection and handshake to the sync server. If the sync server isn't initialized, this will set it up to sync with the local document.
+
${t('sync_2.test_description')}
-
+
`;
export default class SyncOptions extends OptionsWidget {
@@ -58,9 +59,8 @@ export default class SyncOptions extends OptionsWidget {
if (result.success) {
toastService.showMessage(result.message);
- }
- else {
- toastService.showError(`Sync server handshake failed, error: ${result.message}`);
+ } else {
+ toastService.showError(t('sync_2.handshake_failed', { message: result.message }));
}
});
}
diff --git a/src/public/translations/cn/translation.json b/src/public/translations/cn/translation.json
index 2efb60d67..92e94c935 100644
--- a/src/public/translations/cn/translation.json
+++ b/src/public/translations/cn/translation.json
@@ -1194,5 +1194,29 @@
"reload_app": "重新加载应用以应用更改",
"set_all_to_default": "将所有快捷键重置为默认值",
"confirm_reset": "您确定要将所有键盘快捷键重置为默认值吗?"
+ },
+ "spellcheck": {
+ "title": "拼写检查",
+ "description": "这些选项仅适用于桌面版本,浏览器将使用其原生的拼写检查功能。更改后需要重启应用。",
+ "enable": "启用拼写检查",
+ "language_code_label": "语言代码",
+ "language_code_placeholder": "例如 \"en-US\", \"de-AT\"",
+ "multiple_languages_info": "多种语言可以用逗号分隔,例如 \"en-US, de-DE, cs\"。拼写检查选项的更改将在应用重启后生效。",
+ "available_language_codes_label": "可用的语言代码:"
+ },
+ "sync_2": {
+ "config_title": "同步配置",
+ "server_address": "服务器地址",
+ "timeout": "同步超时(单位:毫秒)",
+ "proxy_label": "同步代理服务器(可选)",
+ "note": "注意",
+ "note_description": "代理设置留空则使用系统代理(仅桌面客户端有效)。",
+ "special_value_description": "另一个特殊值是 noproxy,它强制忽略系统代理并遵守 NODE_TLS_REJECT_UNAUTHORIZED。",
+ "save": "保存",
+ "help": "帮助",
+ "test_title": "同步测试",
+ "test_description": "测试和同步服务器之间的连接。如果同步服务器没有初始化,会将本地文档同步到同步服务器上。",
+ "test_button": "测试同步",
+ "handshake_failed": "同步服务器握手失败,错误:{{message}}"
}
}
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index 1fc78b79e..45c7058d0 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1195,5 +1195,29 @@
"reload_app": "Reload app to apply changes",
"set_all_to_default": "Set all shortcuts to the default",
"confirm_reset": "Do you really want to reset all keyboard shortcuts to the default?"
+ },
+ "spellcheck": {
+ "title": "Spell Check",
+ "description": "These options apply only for desktop builds, browsers will use their own native spell check. App restart is required after change.",
+ "enable": "Enable spellcheck",
+ "language_code_label": "Language code(s)",
+ "language_code_placeholder": "for example \"en-US\", \"de-AT\"",
+ "multiple_languages_info": "Multiple languages can be separated by comma, e.g. \"en-US, de-DE, cs\". Changes to the spell check options will take effect after application restart.",
+ "available_language_codes_label": "Available language codes:"
+ },
+ "sync": {
+ "config_title": "Sync Configuration",
+ "server_address": "Server instance address",
+ "timeout": "Sync timeout (milliseconds)",
+ "proxy_label": "Sync proxy server (optional)",
+ "note": "Note",
+ "note_description": "If you leave the proxy setting blank, the system proxy will be used (applies to desktop/electron build only).",
+ "special_value_description": "Another special value is noproxy which forces ignoring even the system proxy and respects NODE_TLS_REJECT_UNAUTHORIZED.",
+ "save": "Save",
+ "help": "Help",
+ "test_title": "Sync Test",
+ "test_description": "This will test the connection and handshake to the sync server. If the sync server isn't initialized, this will set it up to sync with the local document.",
+ "test_button": "Test sync",
+ "handshake_failed": "Sync server handshake failed, error: {{message}}"
}
}
From 34d2f20e16f76ac2e9a8ca81d52fa6c2c282bb6e Mon Sep 17 00:00:00 2001
From: Nriver <6752679+Nriver@users.noreply.github.com>
Date: Thu, 15 Aug 2024 11:31:11 +0800
Subject: [PATCH 06/10] fix translation key
---
src/public/translations/en/translation.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index 45c7058d0..245c371b1 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1205,7 +1205,7 @@
"multiple_languages_info": "Multiple languages can be separated by comma, e.g. \"en-US, de-DE, cs\". Changes to the spell check options will take effect after application restart.",
"available_language_codes_label": "Available language codes:"
},
- "sync": {
+ "sync_2": {
"config_title": "Sync Configuration",
"server_address": "Server instance address",
"timeout": "Sync timeout (milliseconds)",
From 4c3694bfa379e122a7dd42b3108eb8d13530e115 Mon Sep 17 00:00:00 2001
From: Nriver <6752679+Nriver@users.noreply.github.com>
Date: Thu, 15 Aug 2024 11:33:44 +0800
Subject: [PATCH 07/10] add translation for widget: api_log.js
---
src/public/app/widgets/api_log.js | 3 ++-
src/public/translations/cn/translation.json | 3 +++
src/public/translations/en/translation.json | 3 +++
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/public/app/widgets/api_log.js b/src/public/app/widgets/api_log.js
index faa01f108..b1a85a486 100644
--- a/src/public/app/widgets/api_log.js
+++ b/src/public/app/widgets/api_log.js
@@ -1,3 +1,4 @@
+import { t } from "../services/i18n.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js";
const TPL = `
@@ -32,7 +33,7 @@ const TPL = `
}
-
+
`;
diff --git a/src/public/translations/cn/translation.json b/src/public/translations/cn/translation.json
index 92e94c935..882ce1629 100644
--- a/src/public/translations/cn/translation.json
+++ b/src/public/translations/cn/translation.json
@@ -1218,5 +1218,8 @@
"test_description": "测试和同步服务器之间的连接。如果同步服务器没有初始化,会将本地文档同步到同步服务器上。",
"test_button": "测试同步",
"handshake_failed": "同步服务器握手失败,错误:{{message}}"
+ },
+ "api_log": {
+ "close": "关闭"
}
}
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index 245c371b1..8d9eaa5fa 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1219,5 +1219,8 @@
"test_description": "This will test the connection and handshake to the sync server. If the sync server isn't initialized, this will set it up to sync with the local document.",
"test_button": "Test sync",
"handshake_failed": "Sync server handshake failed, error: {{message}}"
+ },
+ "api_log": {
+ "close": "Close"
}
}
From e7eec0f32841d2bdf98a9c8ae98a865135b91a60 Mon Sep 17 00:00:00 2001
From: Nriver <6752679+Nriver@users.noreply.github.com>
Date: Thu, 15 Aug 2024 11:42:30 +0800
Subject: [PATCH 08/10] add translation for widget: attachment_detail.js
---
src/public/app/widgets/attachment_detail.js | 13 +++++++------
src/public/translations/cn/translation.json | 8 ++++++++
src/public/translations/en/translation.json | 8 ++++++++
3 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/src/public/app/widgets/attachment_detail.js b/src/public/app/widgets/attachment_detail.js
index 8c034b8cd..63dc1ff7e 100644
--- a/src/public/app/widgets/attachment_detail.js
+++ b/src/public/app/widgets/attachment_detail.js
@@ -1,3 +1,4 @@
+import { t } from "../services/i18n.js";
import utils from "../services/utils.js";
import AttachmentActionsWidget from "./buttons/attachments_actions.js";
import BasicWidget from "./basic_widget.js";
@@ -153,19 +154,19 @@ export default class AttachmentDetailWidget extends BasicWidget {
$deletionWarning.show();
if (willBeDeletedInMs >= 60000) {
- $deletionWarning.text(`This attachment will be automatically deleted in ${utils.formatTimeInterval(willBeDeletedInMs)}`);
+ $deletionWarning.text(t('attachment_detail_2.will_be_deleted_in', { time: utils.formatTimeInterval(willBeDeletedInMs) }));
} else {
- $deletionWarning.text(`This attachment will be automatically deleted soon`);
+ $deletionWarning.text(t('attachment_detail_2.will_be_deleted_soon'));
}
- $deletionWarning.append(", because the attachment is not linked in the note's content. To prevent deletion, add the attachment link back into the content or convert the attachment into note.");
+ $deletionWarning.append(t('attachment_detail_2.deletion_reason'));
} else {
this.$wrapper.removeClass("scheduled-for-deletion");
$deletionWarning.hide();
}
this.$wrapper.find('.attachment-details')
- .text(`Role: ${this.attachment.role}, Size: ${utils.formatSize(this.attachment.contentLength)}`);
+ .text(t('attachment_detail_2.role_and_size', { role: this.attachment.role, size: utils.formatSize(this.attachment.contentLength) }));
this.$wrapper.find('.attachment-actions-container').append(this.attachmentActionsWidget.render());
const {$renderedContent} = await contentRenderer.getRenderedContent(this.attachment, { imageHasZoom: this.isFullDetail });
@@ -186,9 +187,9 @@ export default class AttachmentDetailWidget extends BasicWidget {
utils.copyHtmlToClipboard($link[0].outerHTML);
- toastService.showMessage("Attachment link copied to clipboard.");
+ toastService.showMessage(t('attachment_detail_2.link_copied'));
} else {
- throw new Error(`Unrecognized attachment role '${this.attachment.role}'.`);
+ throw new Error(t('attachment_detail_2.unrecognized_role', { role: this.attachment.role }));
}
}
diff --git a/src/public/translations/cn/translation.json b/src/public/translations/cn/translation.json
index 882ce1629..349c5d396 100644
--- a/src/public/translations/cn/translation.json
+++ b/src/public/translations/cn/translation.json
@@ -1221,5 +1221,13 @@
},
"api_log": {
"close": "关闭"
+ },
+ "attachment_detail_2": {
+ "will_be_deleted_in": "此附件将在 {{time}} 后自动删除",
+ "will_be_deleted_soon": "该附件将很快被自动删除",
+ "deletion_reason": ",因为该附件未链接在笔记的内容中。为防止被删除,请将附件链接重新添加到内容中或将附件转换为笔记。",
+ "role_and_size": "角色: {{role}}, 大小: {{size}}",
+ "link_copied": "附件链接已复制到剪贴板。",
+ "unrecognized_role": "无法识别的附件角色 '{{role}}'。"
}
}
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index 8d9eaa5fa..425ea4a26 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1222,5 +1222,13 @@
},
"api_log": {
"close": "Close"
+ },
+ "attachment_detail_2": {
+ "will_be_deleted_in": "This attachment will be automatically deleted in {time}}",
+ "will_be_deleted_soon": "This attachment will be automatically deleted soon",
+ "deletion_reason": ", because the attachment is not linked in the note's content. To prevent deletion, add the attachment link back into the content or convert the attachment into note.",
+ "role_and_size": "Role: {{role}}, Size: {{size}}",
+ "link_copied": "Attachment link copied to clipboard.",
+ "unrecognized_role": "Unrecognized attachment role '{{role}}'."
}
}
From 0198f135ac327f316ec0011cf671c5a659d65053 Mon Sep 17 00:00:00 2001
From: Nriver <6752679+Nriver@users.noreply.github.com>
Date: Fri, 16 Aug 2024 11:27:22 +0800
Subject: [PATCH 09/10] Fix duplicated key and missing '{' in translation.json
---
src/public/translations/en/translation.json | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index 425ea4a26..6374c7fcf 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -536,7 +536,6 @@
"delete_success": "Attachment '{{title}}' has been deleted.",
"convert_confirm": "Are you sure you want to convert attachment '{{title}}' into a separate note?",
"convert_success": "Attachment '{{title}}' has been converted to note.",
- "rename_attachment": "Rename attachment",
"enter_new_name": "Please enter new attachment's name"
},
"calendar": {
@@ -1224,7 +1223,7 @@
"close": "Close"
},
"attachment_detail_2": {
- "will_be_deleted_in": "This attachment will be automatically deleted in {time}}",
+ "will_be_deleted_in": "This attachment will be automatically deleted in {{time}}",
"will_be_deleted_soon": "This attachment will be automatically deleted soon",
"deletion_reason": ", because the attachment is not linked in the note's content. To prevent deletion, add the attachment link back into the content or convert the attachment into note.",
"role_and_size": "Role: {{role}}, Size: {{size}}",
From 8e87bcf37b2c523fd3534a16347afb3409c617fc Mon Sep 17 00:00:00 2001
From: Nriver <6752679+Nriver@users.noreply.github.com>
Date: Fri, 16 Aug 2024 11:39:26 +0800
Subject: [PATCH 10/10] add translation for bookmark_switch.js and
editability_select.js
---
src/public/app/widgets/bookmark_switch.js | 9 +++--
src/public/app/widgets/editability_select.js | 41 ++++++++++----------
src/public/translations/cn/translation.json | 13 +++++++
src/public/translations/en/translation.json | 13 +++++++
4 files changed, 52 insertions(+), 24 deletions(-)
diff --git a/src/public/app/widgets/bookmark_switch.js b/src/public/app/widgets/bookmark_switch.js
index 22040e3e8..ab9055df1 100644
--- a/src/public/app/widgets/bookmark_switch.js
+++ b/src/public/app/widgets/bookmark_switch.js
@@ -1,6 +1,7 @@
import SwitchWidget from "./switch.js";
import server from "../services/server.js";
import toastService from "../services/toast.js";
+import { t } from "../services/i18n.js";
export default class BookmarkSwitchWidget extends SwitchWidget {
isEnabled() {
@@ -12,11 +13,11 @@ export default class BookmarkSwitchWidget extends SwitchWidget {
doRender() {
super.doRender();
- this.$switchOnName.text("Bookmark");
- this.$switchOnButton.attr("title", "Bookmark this note to the left side panel");
+ this.$switchOnName.text(t("bookmark_switch.bookmark"));
+ this.$switchOnButton.attr("title", t("bookmark_switch.bookmark_this_note"));
- this.$switchOffName.text("Bookmark");
- this.$switchOffButton.attr("title", "Remove bookmark");
+ this.$switchOffName.text(t("bookmark_switch.bookmark"));
+ this.$switchOffButton.attr("title", t("bookmark_switch.remove_bookmark"));
}
async toggle(state) {
diff --git a/src/public/app/widgets/editability_select.js b/src/public/app/widgets/editability_select.js
index 2cc4f14de..00460be18 100644
--- a/src/public/app/widgets/editability_select.js
+++ b/src/public/app/widgets/editability_select.js
@@ -1,5 +1,6 @@
import attributeService from '../services/attributes.js';
import NoteContextAwareWidget from "./note_context_aware_widget.js";
+import { t } from "../services/i18n.js";
const TPL = `