mirror of
https://github.com/TriliumNext/Trilium.git
synced 2025-12-10 03:53:37 -06:00
Merge remote-tracking branch 'origin/main' into feature/export_with_share_theme
This commit is contained in:
commit
b1f8d44576
2
.github/actions/build-server/action.yml
vendored
2
.github/actions/build-server/action.yml
vendored
@ -12,7 +12,7 @@ runs:
|
|||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 24
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
2
.github/workflows/deploy-docs.yml
vendored
2
.github/workflows/deploy-docs.yml
vendored
@ -74,7 +74,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '22'
|
node-version: '24'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
||||||
# Install Node.js dependencies for the TypeScript script
|
# Install Node.js dependencies for the TypeScript script
|
||||||
|
|||||||
2
.github/workflows/dev.yml
vendored
2
.github/workflows/dev.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 24
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
- run: pnpm install --frozen-lockfile
|
- run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
|||||||
12
.github/workflows/main-docker.yml
vendored
12
.github/workflows/main-docker.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
|||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 24
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
|
||||||
- name: Install npm dependencies
|
- name: Install npm dependencies
|
||||||
@ -86,12 +86,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Playwright trace
|
- name: Upload Playwright trace
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: Playwright trace (${{ matrix.dockerfile }})
|
name: Playwright trace (${{ matrix.dockerfile }})
|
||||||
path: test-output/playwright/output
|
path: test-output/playwright/output
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v5
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
with:
|
with:
|
||||||
name: Playwright report (${{ matrix.dockerfile }})
|
name: Playwright report (${{ matrix.dockerfile }})
|
||||||
@ -146,7 +146,7 @@ jobs:
|
|||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 24
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@ -209,7 +209,7 @@ jobs:
|
|||||||
touch "/tmp/digests/${digest#sha256:}"
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
|
|
||||||
- name: Upload digest
|
- name: Upload digest
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: digests-${{ env.PLATFORM_PAIR }}-${{ matrix.dockerfile }}
|
name: digests-${{ env.PLATFORM_PAIR }}-${{ matrix.dockerfile }}
|
||||||
path: /tmp/digests/*
|
path: /tmp/digests/*
|
||||||
@ -223,7 +223,7 @@ jobs:
|
|||||||
- build
|
- build
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v6
|
||||||
with:
|
with:
|
||||||
path: /tmp/digests
|
path: /tmp/digests
|
||||||
pattern: digests-*
|
pattern: digests-*
|
||||||
|
|||||||
4
.github/workflows/nightly.yml
vendored
4
.github/workflows/nightly.yml
vendored
@ -52,7 +52,7 @@ jobs:
|
|||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 24
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@ -89,7 +89,7 @@ jobs:
|
|||||||
name: Nightly Build
|
name: Nightly Build
|
||||||
|
|
||||||
- name: Publish artifacts
|
- name: Publish artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
name: TriliumNotes ${{ matrix.os.name }} ${{ matrix.arch }}
|
name: TriliumNotes ${{ matrix.os.name }} ${{ matrix.arch }}
|
||||||
|
|||||||
4
.github/workflows/playwright.yml
vendored
4
.github/workflows/playwright.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
|||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 24
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@ -35,7 +35,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload test report
|
- name: Upload test report
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: e2e report
|
name: e2e report
|
||||||
path: apps/server-e2e/test-output
|
path: apps/server-e2e/test-output
|
||||||
|
|||||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@ -50,7 +50,7 @@ jobs:
|
|||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 24
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
@ -73,7 +73,7 @@ jobs:
|
|||||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
||||||
|
|
||||||
- name: Upload the artifact
|
- name: Upload the artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: release-desktop-${{ matrix.os.name }}-${{ matrix.arch }}
|
name: release-desktop-${{ matrix.os.name }}-${{ matrix.arch }}
|
||||||
path: apps/desktop/upload/*.*
|
path: apps/desktop/upload/*.*
|
||||||
@ -100,7 +100,7 @@ jobs:
|
|||||||
arch: ${{ matrix.arch }}
|
arch: ${{ matrix.arch }}
|
||||||
|
|
||||||
- name: Upload the artifact
|
- name: Upload the artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: release-server-linux-${{ matrix.arch }}
|
name: release-server-linux-${{ matrix.arch }}
|
||||||
path: upload/*.*
|
path: upload/*.*
|
||||||
@ -120,7 +120,7 @@ jobs:
|
|||||||
docs/Release Notes
|
docs/Release Notes
|
||||||
|
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v6
|
||||||
with:
|
with:
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
pattern: release-*
|
pattern: release-*
|
||||||
|
|||||||
2
.github/workflows/website.yml
vendored
2
.github/workflows/website.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 24
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
|||||||
@ -37,9 +37,9 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "1.56.1",
|
"@playwright/test": "1.56.1",
|
||||||
"@stylistic/eslint-plugin": "5.5.0",
|
"@stylistic/eslint-plugin": "5.5.0",
|
||||||
"@types/express": "5.0.3",
|
"@types/express": "5.0.5",
|
||||||
"@types/node": "22.18.12",
|
"@types/node": "24.9.1",
|
||||||
"@types/yargs": "17.0.33",
|
"@types/yargs": "17.0.34",
|
||||||
"@vitest/coverage-v8": "3.2.4",
|
"@vitest/coverage-v8": "3.2.4",
|
||||||
"eslint": "9.38.0",
|
"eslint": "9.38.0",
|
||||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||||
|
|||||||
@ -54,12 +54,12 @@
|
|||||||
"leaflet-gpx": "2.2.0",
|
"leaflet-gpx": "2.2.0",
|
||||||
"mark.js": "8.11.1",
|
"mark.js": "8.11.1",
|
||||||
"marked": "16.4.1",
|
"marked": "16.4.1",
|
||||||
"mermaid": "11.12.0",
|
"mermaid": "11.12.1",
|
||||||
"mind-elixir": "5.3.3",
|
"mind-elixir": "5.3.4",
|
||||||
"normalize.css": "8.0.1",
|
"normalize.css": "8.0.1",
|
||||||
"panzoom": "9.4.3",
|
"panzoom": "9.4.3",
|
||||||
"preact": "10.27.2",
|
"preact": "10.27.2",
|
||||||
"react-i18next": "16.1.2",
|
"react-i18next": "16.2.1",
|
||||||
"reveal.js": "5.2.1",
|
"reveal.js": "5.2.1",
|
||||||
"svg-pan-zoom": "3.6.2",
|
"svg-pan-zoom": "3.6.2",
|
||||||
"tabulator-tables": "6.3.1",
|
"tabulator-tables": "6.3.1",
|
||||||
@ -74,9 +74,9 @@
|
|||||||
"@types/leaflet-gpx": "1.3.8",
|
"@types/leaflet-gpx": "1.3.8",
|
||||||
"@types/mark.js": "8.11.12",
|
"@types/mark.js": "8.11.12",
|
||||||
"@types/reveal.js": "5.2.1",
|
"@types/reveal.js": "5.2.1",
|
||||||
"@types/tabulator-tables": "6.2.11",
|
"@types/tabulator-tables": "6.3.0",
|
||||||
"copy-webpack-plugin": "13.0.1",
|
"copy-webpack-plugin": "13.0.1",
|
||||||
"happy-dom": "20.0.7",
|
"happy-dom": "20.0.8",
|
||||||
"script-loader": "0.7.2",
|
"script-loader": "0.7.2",
|
||||||
"vite-plugin-static-copy": "3.1.4"
|
"vite-plugin-static-copy": "3.1.4"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -218,12 +218,12 @@ export type CommandMappings = {
|
|||||||
/** Works only in the electron context menu. */
|
/** Works only in the electron context menu. */
|
||||||
replaceMisspelling: CommandData;
|
replaceMisspelling: CommandData;
|
||||||
|
|
||||||
importMarkdownInline: CommandData;
|
|
||||||
showPasswordNotSet: CommandData;
|
showPasswordNotSet: CommandData;
|
||||||
showProtectedSessionPasswordDialog: CommandData;
|
showProtectedSessionPasswordDialog: CommandData;
|
||||||
showUploadAttachmentsDialog: CommandData & { noteId: string };
|
showUploadAttachmentsDialog: CommandData & { noteId: string };
|
||||||
showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
|
showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
|
||||||
showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string };
|
showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string };
|
||||||
|
showPasteMarkdownDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
|
||||||
closeProtectedSessionPasswordDialog: CommandData;
|
closeProtectedSessionPasswordDialog: CommandData;
|
||||||
copyImageReferenceToClipboard: CommandData;
|
copyImageReferenceToClipboard: CommandData;
|
||||||
copyImageToClipboard: CommandData;
|
copyImageToClipboard: CommandData;
|
||||||
|
|||||||
@ -56,7 +56,20 @@ function SingleNoteRenderer({ note, onReady }: RendererProps) {
|
|||||||
await import("@triliumnext/ckeditor5/src/theme/ck-content.css");
|
await import("@triliumnext/ckeditor5/src/theme/ck-content.css");
|
||||||
}
|
}
|
||||||
const { $renderedContent } = await content_renderer.getRenderedContent(note, { noChildrenList: true });
|
const { $renderedContent } = await content_renderer.getRenderedContent(note, { noChildrenList: true });
|
||||||
containerRef.current?.replaceChildren(...$renderedContent);
|
const container = containerRef.current!;
|
||||||
|
container.replaceChildren(...$renderedContent);
|
||||||
|
|
||||||
|
// Wait for all images to load.
|
||||||
|
const images = Array.from(container.querySelectorAll("img"));
|
||||||
|
await Promise.all(
|
||||||
|
images.map(img => {
|
||||||
|
if (img.complete) return Promise.resolve();
|
||||||
|
return new Promise<void>(resolve => {
|
||||||
|
img.addEventListener("load", () => resolve(), { once: true });
|
||||||
|
img.addEventListener("error", () => resolve(), { once: true });
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
load().then(() => requestAnimationFrame(onReady))
|
load().then(() => requestAnimationFrame(onReady))
|
||||||
|
|||||||
@ -20,9 +20,6 @@ function setupGlobs() {
|
|||||||
window.glob.froca = froca;
|
window.glob.froca = froca;
|
||||||
window.glob.treeCache = froca; // compatibility for CKEditor builds for a while
|
window.glob.treeCache = froca; // compatibility for CKEditor builds for a while
|
||||||
|
|
||||||
// for CKEditor integration (button on block toolbar)
|
|
||||||
window.glob.importMarkdownInline = async () => appContext.triggerCommand("importMarkdownInline");
|
|
||||||
|
|
||||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||||
const string = String(msg).toLowerCase();
|
const string = String(msg).toLowerCase();
|
||||||
|
|
||||||
|
|||||||
@ -2034,9 +2034,9 @@ body.zen #right-pane,
|
|||||||
body.zen #mobile-sidebar-wrapper,
|
body.zen #mobile-sidebar-wrapper,
|
||||||
body.zen .tab-row-container,
|
body.zen .tab-row-container,
|
||||||
body.zen .tab-row-widget,
|
body.zen .tab-row-widget,
|
||||||
body.zen .ribbon-container:not(:has(.classic-toolbar-widget.visible)),
|
body.zen .ribbon-container:not(:has(.classic-toolbar-widget)),
|
||||||
body.zen .ribbon-container:has(.classic-toolbar-widget.visible) .ribbon-top-row,
|
body.zen .ribbon-container:has(.classic-toolbar-widget) .ribbon-top-row,
|
||||||
body.zen .ribbon-container .ribbon-body:not(:has(.classic-toolbar-widget.visible)),
|
body.zen .ribbon-container .ribbon-body:not(:has(.classic-toolbar-widget)),
|
||||||
body.zen .note-icon-widget,
|
body.zen .note-icon-widget,
|
||||||
body.zen .title-row .icon-action,
|
body.zen .title-row .icon-action,
|
||||||
body.zen .floating-buttons-children > *:not(.bx-edit-alt),
|
body.zen .floating-buttons-children > *:not(.bx-edit-alt),
|
||||||
|
|||||||
@ -12,6 +12,9 @@
|
|||||||
"toast": {
|
"toast": {
|
||||||
"critical-error": {
|
"critical-error": {
|
||||||
"title": "خطأ فادح"
|
"title": "خطأ فادح"
|
||||||
|
},
|
||||||
|
"widget-error": {
|
||||||
|
"title": "فشل في البدء بعنصر الواجهة"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"add_link": {
|
"add_link": {
|
||||||
@ -26,7 +29,8 @@
|
|||||||
"edit_branch_prefix": "تعديل بادئة الفرع",
|
"edit_branch_prefix": "تعديل بادئة الفرع",
|
||||||
"prefix": "البادئة: ",
|
"prefix": "البادئة: ",
|
||||||
"save": "حفظ",
|
"save": "حفظ",
|
||||||
"help_on_tree_prefix": "مساعدة حول بادئة الشجرة"
|
"help_on_tree_prefix": "مساعدة حول بادئة الشجرة",
|
||||||
|
"branch_prefix_saved": "تم حفظ بادئة الفرع."
|
||||||
},
|
},
|
||||||
"bulk_actions": {
|
"bulk_actions": {
|
||||||
"bulk_actions": "اجراءات جماعية",
|
"bulk_actions": "اجراءات جماعية",
|
||||||
@ -83,7 +87,8 @@
|
|||||||
"workspace_calendar_root": "تحديد جذر التقويم لكل مساحة عمل",
|
"workspace_calendar_root": "تحديد جذر التقويم لكل مساحة عمل",
|
||||||
"hide_highlight_widget": "اخفاء عنصر واجهة قائمة التمييزات",
|
"hide_highlight_widget": "اخفاء عنصر واجهة قائمة التمييزات",
|
||||||
"is_owned_by_note": "تخص الملاحظة",
|
"is_owned_by_note": "تخص الملاحظة",
|
||||||
"and_more": "... و {{count}}مرات اكثر."
|
"and_more": "... و {{count}}مرات اكثر.",
|
||||||
|
"related_notes_title": "ملاحظات اخرى بنفس التسمية"
|
||||||
},
|
},
|
||||||
"rename_label": {
|
"rename_label": {
|
||||||
"to": "الى",
|
"to": "الى",
|
||||||
@ -127,7 +132,9 @@
|
|||||||
"delete_attachment": "حذف المرفق",
|
"delete_attachment": "حذف المرفق",
|
||||||
"upload_new_revision": "رفع مراجعة جديدة",
|
"upload_new_revision": "رفع مراجعة جديدة",
|
||||||
"copy_link_to_clipboard": "نسخ الرابط الى الحافظة",
|
"copy_link_to_clipboard": "نسخ الرابط الى الحافظة",
|
||||||
"convert_attachment_into_note": "تحويل المرفق الى ملاحظة"
|
"convert_attachment_into_note": "تحويل المرفق الى ملاحظة",
|
||||||
|
"delete_success": "تم حذف المرفق \"{{title}}\" .",
|
||||||
|
"enter_new_name": "ادخل اسم مرفق جديد"
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"week": "أسبوع",
|
"week": "أسبوع",
|
||||||
@ -259,7 +266,8 @@
|
|||||||
"note_paths": {
|
"note_paths": {
|
||||||
"search": "بحث",
|
"search": "بحث",
|
||||||
"archived": "مؤرشف",
|
"archived": "مؤرشف",
|
||||||
"title": "مسارات الملاحظة"
|
"title": "مسارات الملاحظة",
|
||||||
|
"clone_button": "جار نسخ الملاحظة الى مكان جديد..."
|
||||||
},
|
},
|
||||||
"script_executor": {
|
"script_executor": {
|
||||||
"query": "استعلام",
|
"query": "استعلام",
|
||||||
@ -372,7 +380,8 @@
|
|||||||
"export_note_title": "تصدير الملاحظة",
|
"export_note_title": "تصدير الملاحظة",
|
||||||
"export_status": "حالة التصدير",
|
"export_status": "حالة التصدير",
|
||||||
"export_finished_successfully": "اكتمل التصدير بنجاح.",
|
"export_finished_successfully": "اكتمل التصدير بنجاح.",
|
||||||
"export_in_progress": "جار التصدير: {{progressCount}}"
|
"export_in_progress": "جار التصدير: {{progressCount}}",
|
||||||
|
"choose_export_type": "اختر نوع التصدير اولا من فضلك"
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"troubleshooting": "أستكشاف الاخطاء واصلاحها",
|
"troubleshooting": "أستكشاف الاخطاء واصلاحها",
|
||||||
@ -402,7 +411,10 @@
|
|||||||
"movingCloningNotes": "نقل/ استنساخ الملاحظات",
|
"movingCloningNotes": "نقل/ استنساخ الملاحظات",
|
||||||
"deleteNotes": "حذف الملاحظة/ الشجرة الفرعية",
|
"deleteNotes": "حذف الملاحظة/ الشجرة الفرعية",
|
||||||
"collapseWholeTree": "طي شجرة الملاحظة باكملها",
|
"collapseWholeTree": "طي شجرة الملاحظة باكملها",
|
||||||
"followLink": "اتبع تلرابط تحت المؤشر"
|
"followLink": "اتبع تلرابط تحت المؤشر",
|
||||||
|
"onlyInDesktop": "في سطح المكتب فقط(Electron build)",
|
||||||
|
"createEditLink": "انشاء/ تحرير رابط خارجي",
|
||||||
|
"quickSearch": "الانتقال الى مربع البحث السريع"
|
||||||
},
|
},
|
||||||
"import": {
|
"import": {
|
||||||
"options": "خيارات",
|
"options": "خيارات",
|
||||||
@ -465,7 +477,13 @@
|
|||||||
"delete_all_button": "حذف كل المراجعات",
|
"delete_all_button": "حذف كل المراجعات",
|
||||||
"settings": "اعدادات مراجعة الملاحظة",
|
"settings": "اعدادات مراجعة الملاحظة",
|
||||||
"diff_not_available": "المقارنة غير متوفرة.",
|
"diff_not_available": "المقارنة غير متوفرة.",
|
||||||
"help_title": "مساعدة حول مراجعات الملاحظة"
|
"help_title": "مساعدة حول مراجعات الملاحظة",
|
||||||
|
"diff_off_hint": "انقر لعرض محتويات الملاحظة",
|
||||||
|
"revisions_deleted": "تم حذف جميع نسخ المراجعات للملاحظة.",
|
||||||
|
"revision_restored": "تم استعادة نسخ المراجعة للملاحظة.",
|
||||||
|
"revision_deleted": "تم حذف مراجعة الملاحظة.",
|
||||||
|
"snapshot_interval": "فاصل زمني لحفظ لقطات اصدارات المراجعة: {{seconds}}",
|
||||||
|
"maximum_revisions": "حد عدد لقطات اصدارات الملاحظة: {{number}}"
|
||||||
},
|
},
|
||||||
"sort_child_notes": {
|
"sort_child_notes": {
|
||||||
"title": "عنوان",
|
"title": "عنوان",
|
||||||
@ -479,13 +497,15 @@
|
|||||||
"sorting_direction": "اتجاه الترتيب",
|
"sorting_direction": "اتجاه الترتيب",
|
||||||
"natural_sort": "الترتيب الطبيعي",
|
"natural_sort": "الترتيب الطبيعي",
|
||||||
"natural_sort_language": "لغات الترتيب الطبيعي",
|
"natural_sort_language": "لغات الترتيب الطبيعي",
|
||||||
"sort_children_by": "ترتيب العناصر الفرعية حسب..."
|
"sort_children_by": "ترتيب العناصر الفرعية حسب...",
|
||||||
|
"sort_folders_at_top": "ترتيب المجلدات في الاعلى"
|
||||||
},
|
},
|
||||||
"recent_changes": {
|
"recent_changes": {
|
||||||
"undelete_link": "الغاء الحذف",
|
"undelete_link": "الغاء الحذف",
|
||||||
"title": "التغيرات الاخيرة",
|
"title": "التغيرات الاخيرة",
|
||||||
"no_changes_message": "لايوجد تغيير لحد الان...",
|
"no_changes_message": "لايوجد تغيير لحد الان...",
|
||||||
"erase_notes_button": "مسح الملاحظات المحذوفة الان"
|
"erase_notes_button": "مسح الملاحظات المحذوفة الان",
|
||||||
|
"deleted_notes_message": "تم حذف الملاحظات نهائيا."
|
||||||
},
|
},
|
||||||
"edited_notes": {
|
"edited_notes": {
|
||||||
"deleted": "(حذف)",
|
"deleted": "(حذف)",
|
||||||
@ -705,7 +725,9 @@
|
|||||||
"default_token_name": "رمز جديد",
|
"default_token_name": "رمز جديد",
|
||||||
"rename_token_title": "اعادة تسمية الرمز",
|
"rename_token_title": "اعادة تسمية الرمز",
|
||||||
"rename_token": "اعادة تسمية هذا الرمز",
|
"rename_token": "اعادة تسمية هذا الرمز",
|
||||||
"create_token": "انشاء رمز PEAPI جديد"
|
"create_token": "انشاء رمز PEAPI جديد",
|
||||||
|
"new_token_title": "رمز ETAPI جديد",
|
||||||
|
"token_created_title": "انشاء رمز ETAPI"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"heading": "كلمة المرور",
|
"heading": "كلمة المرور",
|
||||||
@ -811,7 +833,8 @@
|
|||||||
"help_on_links": "مساعدة حول الارتباطات التشعبية",
|
"help_on_links": "مساعدة حول الارتباطات التشعبية",
|
||||||
"notes_to_clone": "ملاحظات للنسخ",
|
"notes_to_clone": "ملاحظات للنسخ",
|
||||||
"target_parent_note": "الملاحظة الاصلية الهدف",
|
"target_parent_note": "الملاحظة الاصلية الهدف",
|
||||||
"clone_to_selected_note": "استنساخ الى الملاحظة المحددة"
|
"clone_to_selected_note": "استنساخ الى الملاحظة المحددة",
|
||||||
|
"no_path_to_clone_to": "لايوجد مسار لنسخ المحتوى الية."
|
||||||
},
|
},
|
||||||
"table_of_contents": {
|
"table_of_contents": {
|
||||||
"unit": "عناوين",
|
"unit": "عناوين",
|
||||||
@ -1029,7 +1052,8 @@
|
|||||||
},
|
},
|
||||||
"delete_note": {
|
"delete_note": {
|
||||||
"delete_note": "حذف الملاحظة",
|
"delete_note": "حذف الملاحظة",
|
||||||
"delete_matched_notes": "حف الملاحظات المطابقة"
|
"delete_matched_notes": "حف الملاحظات المطابقة",
|
||||||
|
"delete_matched_notes_description": "سوف يؤدي هذا الى حذف الملاحظات المطابقة."
|
||||||
},
|
},
|
||||||
"rename_note": {
|
"rename_note": {
|
||||||
"rename_note": "اعادة تسمية الملاحظة",
|
"rename_note": "اعادة تسمية الملاحظة",
|
||||||
@ -1312,7 +1336,8 @@
|
|||||||
"notes_to_move": "الملاحظات المراد نقلها",
|
"notes_to_move": "الملاحظات المراد نقلها",
|
||||||
"target_parent_note": "ملاحظة الاصل الهدف",
|
"target_parent_note": "ملاحظة الاصل الهدف",
|
||||||
"dialog_title": "انقل الملاحظات الى...",
|
"dialog_title": "انقل الملاحظات الى...",
|
||||||
"move_button": "نقل الىالملاحظة المحددة"
|
"move_button": "نقل الىالملاحظة المحددة",
|
||||||
|
"error_no_path": "لايوجد مسار لنقل العنصر الية."
|
||||||
},
|
},
|
||||||
"delete_revisions": {
|
"delete_revisions": {
|
||||||
"delete_note_revisions": "حذف مراجعات الملاحظة"
|
"delete_note_revisions": "حذف مراجعات الملاحظة"
|
||||||
@ -1363,7 +1388,8 @@
|
|||||||
"save_attributes": "حفظ السمات <enter>",
|
"save_attributes": "حفظ السمات <enter>",
|
||||||
"add_a_new_attribute": "اضافة سمة جديدة",
|
"add_a_new_attribute": "اضافة سمة جديدة",
|
||||||
"add_new_label_definition": "اضافة تعريف لتسمية جديدة",
|
"add_new_label_definition": "اضافة تعريف لتسمية جديدة",
|
||||||
"add_new_relation_definition": "اضافة تعريف لعلاقة جديدة"
|
"add_new_relation_definition": "اضافة تعريف لعلاقة جديدة",
|
||||||
|
"add_new_relation": "اضافة علاقة جديدة <kbd data-command=\"addNewRelation\">"
|
||||||
},
|
},
|
||||||
"zen_mode": {
|
"zen_mode": {
|
||||||
"button_exit": "الخروج من وضع Zen"
|
"button_exit": "الخروج من وضع Zen"
|
||||||
@ -1434,5 +1460,8 @@
|
|||||||
},
|
},
|
||||||
"png_export_button": {
|
"png_export_button": {
|
||||||
"button_title": "تصدير المخطط كملف PNG"
|
"button_title": "تصدير المخطط كملف PNG"
|
||||||
|
},
|
||||||
|
"protected_session_status": {
|
||||||
|
"inactive": "انقر للدخول الى جلسة محمية"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"homepage": "Startseite:",
|
"homepage": "Startseite:",
|
||||||
"app_version": "App-Version:",
|
"app_version": "App-Version:",
|
||||||
"db_version": "DB-Version:",
|
"db_version": "DB-Version:",
|
||||||
"sync_version": "Synch-version:",
|
"sync_version": "Sync-Version:",
|
||||||
"build_date": "Build-Datum:",
|
"build_date": "Build-Datum:",
|
||||||
"build_revision": "Build-Revision:",
|
"build_revision": "Build-Revision:",
|
||||||
"data_directory": "Datenverzeichnis:"
|
"data_directory": "Datenverzeichnis:"
|
||||||
@ -184,7 +184,8 @@
|
|||||||
},
|
},
|
||||||
"import-status": "Importstatus",
|
"import-status": "Importstatus",
|
||||||
"in-progress": "Import läuft: {{progress}}",
|
"in-progress": "Import läuft: {{progress}}",
|
||||||
"successful": "Import erfolgreich abgeschlossen."
|
"successful": "Import erfolgreich abgeschlossen.",
|
||||||
|
"importZipRecommendation": "Beim Import einer ZIP-Datei wird die Notizhierarchie aus der Ordnerstruktur im Archiv übernommen."
|
||||||
},
|
},
|
||||||
"include_note": {
|
"include_note": {
|
||||||
"dialog_title": "Notiz beifügen",
|
"dialog_title": "Notiz beifügen",
|
||||||
@ -647,7 +648,8 @@
|
|||||||
"logout": "Abmelden",
|
"logout": "Abmelden",
|
||||||
"show-cheatsheet": "Cheatsheet anzeigen",
|
"show-cheatsheet": "Cheatsheet anzeigen",
|
||||||
"toggle-zen-mode": "Zen Modus",
|
"toggle-zen-mode": "Zen Modus",
|
||||||
"new-version-available": "Neues Update verfügbar"
|
"new-version-available": "Neues Update verfügbar",
|
||||||
|
"download-update": "Version {{latestVersion}} herunterladen"
|
||||||
},
|
},
|
||||||
"sync_status": {
|
"sync_status": {
|
||||||
"unknown": "<p>Der Synchronisations-Status wird bekannt, sobald der nächste Synchronisierungsversuch gestartet wird.</p><p>Klicke, um eine Synchronisierung jetzt auszulösen.</p>",
|
"unknown": "<p>Der Synchronisations-Status wird bekannt, sobald der nächste Synchronisierungsversuch gestartet wird.</p><p>Klicke, um eine Synchronisierung jetzt auszulösen.</p>",
|
||||||
@ -989,7 +991,7 @@
|
|||||||
"enter_password_instruction": "Um die geschützte Notiz anzuzeigen, musst du dein Passwort eingeben:",
|
"enter_password_instruction": "Um die geschützte Notiz anzuzeigen, musst du dein Passwort eingeben:",
|
||||||
"start_session_button": "Starte eine geschützte Sitzung <kbd>Eingabetaste</kbd>",
|
"start_session_button": "Starte eine geschützte Sitzung <kbd>Eingabetaste</kbd>",
|
||||||
"started": "Geschützte Sitzung gestartet.",
|
"started": "Geschützte Sitzung gestartet.",
|
||||||
"wrong_password": "Passwort flasch.",
|
"wrong_password": "Passwort falsch.",
|
||||||
"protecting-finished-successfully": "Geschützt erfolgreich beendet.",
|
"protecting-finished-successfully": "Geschützt erfolgreich beendet.",
|
||||||
"unprotecting-finished-successfully": "Ungeschützt erfolgreich beendet.",
|
"unprotecting-finished-successfully": "Ungeschützt erfolgreich beendet.",
|
||||||
"protecting-in-progress": "Schützen läuft: {{count}}",
|
"protecting-in-progress": "Schützen läuft: {{count}}",
|
||||||
@ -1521,7 +1523,9 @@
|
|||||||
"window-on-top": "Dieses Fenster immer oben halten"
|
"window-on-top": "Dieses Fenster immer oben halten"
|
||||||
},
|
},
|
||||||
"note_detail": {
|
"note_detail": {
|
||||||
"could_not_find_typewidget": "Konnte typeWidget für Typ ‚{{type}}‘ nicht finden"
|
"could_not_find_typewidget": "Konnte typeWidget für Typ ‚{{type}}‘ nicht finden",
|
||||||
|
"printing": "Druckvorgang läuft…",
|
||||||
|
"printing_pdf": "PDF-Export läuft…"
|
||||||
},
|
},
|
||||||
"note_title": {
|
"note_title": {
|
||||||
"placeholder": "Titel der Notiz hier eingeben…"
|
"placeholder": "Titel der Notiz hier eingeben…"
|
||||||
@ -1654,7 +1658,7 @@
|
|||||||
"add-term-to-dictionary": "Begriff \"{{term}}\" zum Wörterbuch hinzufügen",
|
"add-term-to-dictionary": "Begriff \"{{term}}\" zum Wörterbuch hinzufügen",
|
||||||
"cut": "Ausschneiden",
|
"cut": "Ausschneiden",
|
||||||
"copy": "Kopieren",
|
"copy": "Kopieren",
|
||||||
"copy-link": "Link opieren",
|
"copy-link": "Link kopieren",
|
||||||
"paste": "Einfügen",
|
"paste": "Einfügen",
|
||||||
"paste-as-plain-text": "Als unformatierten Text einfügen",
|
"paste-as-plain-text": "Als unformatierten Text einfügen",
|
||||||
"search_online": "Suche nach \"{{term}}\" mit {{searchEngine}} starten"
|
"search_online": "Suche nach \"{{term}}\" mit {{searchEngine}} starten"
|
||||||
@ -2079,6 +2083,7 @@
|
|||||||
},
|
},
|
||||||
"presentation_view": {
|
"presentation_view": {
|
||||||
"edit-slide": "Folie bearbeiten",
|
"edit-slide": "Folie bearbeiten",
|
||||||
"start-presentation": "Präsentation starten"
|
"start-presentation": "Präsentation starten",
|
||||||
|
"slide-overview": "Übersicht der Folien ein-/ausblenden"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
apps/client/src/translations/hi/translation.json
Normal file
5
apps/client/src/translations/hi/translation.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"about": {
|
||||||
|
"title": "ट्रिलियम नोट्स के बारें में"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1 +1,50 @@
|
|||||||
{}
|
{
|
||||||
|
"about": {
|
||||||
|
"title": "A Trilium Notes-ról",
|
||||||
|
"homepage": "Kezdőlap:",
|
||||||
|
"app_version": "Alkalmazás verziója:",
|
||||||
|
"db_version": "Adatbázis verzió:",
|
||||||
|
"sync_version": "Verzió szinkronizálás :",
|
||||||
|
"build_revision": "Build revízió:",
|
||||||
|
"data_directory": "Adatkönyvtár:",
|
||||||
|
"build_date": "Build dátum:"
|
||||||
|
},
|
||||||
|
"toast": {
|
||||||
|
"critical-error": {
|
||||||
|
"title": "Kritikus hiba",
|
||||||
|
"message": "Kritikus hiba történt, amely megakadályozza a kliensalkalmazás indítását:\n\n{{message}}\n\nEzt valószínűleg egy váratlan szkripthiba okozza. Próbálja meg biztonságos módban elindítani az alkalmazást, és hárítsa el a problémát."
|
||||||
|
},
|
||||||
|
"widget-error": {
|
||||||
|
"title": "Nem sikerült inicializálni egy widgetet",
|
||||||
|
"message-custom": "A(z) \"{{id}}\" azonosítójú, \"{{title}}\" című jegyzetből származó egyéni widget inicializálása sikertelen volt a következő ok miatt:\n\n{{message}}",
|
||||||
|
"message-unknown": "Ismeretlen widget inicializálása sikertelen volt a következő ok miatt:\n\n{{message}}"
|
||||||
|
},
|
||||||
|
"bundle-error": {
|
||||||
|
"title": "Nem sikerült betölteni az egyéni szkriptet",
|
||||||
|
"message": "A(z) \"{{id}}\" azonosítójú, \"{{title}}\" című jegyzetből származó szkript nem hajtható végre a következő ok miatt:\n\n{{message}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"add_link": {
|
||||||
|
"add_link": "Link hozzáadása",
|
||||||
|
"help_on_links": "Segítség a linkekhez",
|
||||||
|
"note": "Jegyzet",
|
||||||
|
"search_note": "név szerinti jegyzetkeresés",
|
||||||
|
"link_title_mirrors": "A link cím tükrözi a jegyzet aktuális címét",
|
||||||
|
"link_title_arbitrary": "link cím önkényesen módosítható",
|
||||||
|
"link_title": "Link cím",
|
||||||
|
"button_add_link": "Link hozzáadása"
|
||||||
|
},
|
||||||
|
"branch_prefix": {
|
||||||
|
"edit_branch_prefix": "Az elágazás előtagjának szerkesztése",
|
||||||
|
"help_on_tree_prefix": "Segítség a fa előtagján",
|
||||||
|
"prefix": "Az előtag: ",
|
||||||
|
"save": "Mentés"
|
||||||
|
},
|
||||||
|
"bulk_actions": {
|
||||||
|
"bulk_actions": "Tömeges akciók",
|
||||||
|
"affected_notes": "Érintett jegyzetek",
|
||||||
|
"labels": "Címkék",
|
||||||
|
"relations": "Kapcsolatok",
|
||||||
|
"notes": "Jegyzetek"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -13,6 +13,13 @@
|
|||||||
"critical-error": {
|
"critical-error": {
|
||||||
"title": "Kritische Error",
|
"title": "Kritische Error",
|
||||||
"message": "Een kritieke fout heeft plaatsgevonden waardoor de cliënt zich aanmeldt vanaf het begin:\n\n84X\n\nDit is waarschijnlijk veroorzaakt door een script dat op een onverwachte manier faalt. Probeer de sollicitatie in veilige modus te starten en de kwestie aan te spreken."
|
"message": "Een kritieke fout heeft plaatsgevonden waardoor de cliënt zich aanmeldt vanaf het begin:\n\n84X\n\nDit is waarschijnlijk veroorzaakt door een script dat op een onverwachte manier faalt. Probeer de sollicitatie in veilige modus te starten en de kwestie aan te spreken."
|
||||||
|
},
|
||||||
|
"widget-error": {
|
||||||
|
"title": "Starten widget mislukt",
|
||||||
|
"message-unknown": "Onbekende widget kan niet gestart worden omdat:\n\n{{message}}"
|
||||||
|
},
|
||||||
|
"bundle-error": {
|
||||||
|
"title": "Custom script laden mislukt"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"add_link": {
|
"add_link": {
|
||||||
|
|||||||
@ -320,7 +320,8 @@
|
|||||||
"explodeArchivesTooltip": "Если этот флажок установлен, Trilium будет читать файлы <code>.zip</code>, <code>.enex</code> и <code>.opml</code> и создавать заметки из файлов внутри этих архивов. Если флажок не установлен, Trilium будет прикреплять сами архивы к заметке.",
|
"explodeArchivesTooltip": "Если этот флажок установлен, Trilium будет читать файлы <code>.zip</code>, <code>.enex</code> и <code>.opml</code> и создавать заметки из файлов внутри этих архивов. Если флажок не установлен, Trilium будет прикреплять сами архивы к заметке.",
|
||||||
"explodeArchives": "Прочитать содержимое архивов <code>.zip</code>, <code>.enex</code> и <code>.opml</code>.",
|
"explodeArchives": "Прочитать содержимое архивов <code>.zip</code>, <code>.enex</code> и <code>.opml</code>.",
|
||||||
"shrinkImagesTooltip": "<p>Если этот параметр включен, Trilium попытается уменьшить размер импортируемых изображений путём масштабирования и оптимизации, что может повлиять на воспринимаемое качество изображения. Если этот параметр не установлен, изображения будут импортированы без изменений.</p><p>Это не относится к импорту файлов <code>.zip</code> с метаданными, поскольку предполагается, что эти файлы уже оптимизированы.</p>",
|
"shrinkImagesTooltip": "<p>Если этот параметр включен, Trilium попытается уменьшить размер импортируемых изображений путём масштабирования и оптимизации, что может повлиять на воспринимаемое качество изображения. Если этот параметр не установлен, изображения будут импортированы без изменений.</p><p>Это не относится к импорту файлов <code>.zip</code> с метаданными, поскольку предполагается, что эти файлы уже оптимизированы.</p>",
|
||||||
"codeImportedAsCode": "Импортировать распознанные файлы кода (например, <code>.json</code>) в виде заметок типа \"код\", если это неясно из метаданных"
|
"codeImportedAsCode": "Импортировать распознанные файлы кода (например, <code>.json</code>) в виде заметок типа \"код\", если это неясно из метаданных",
|
||||||
|
"importZipRecommendation": "При импорте ZIP файла иерархия заметок будет отражена в структуре папок внутри архива."
|
||||||
},
|
},
|
||||||
"markdown_import": {
|
"markdown_import": {
|
||||||
"dialog_title": "Импорт Markdown",
|
"dialog_title": "Импорт Markdown",
|
||||||
@ -980,7 +981,8 @@
|
|||||||
"open_sql_console_history": "Открыть историю консоли SQL",
|
"open_sql_console_history": "Открыть историю консоли SQL",
|
||||||
"show_shared_notes_subtree": "Поддерево общедоступных заметок",
|
"show_shared_notes_subtree": "Поддерево общедоступных заметок",
|
||||||
"switch_to_mobile_version": "Перейти на мобильную версию",
|
"switch_to_mobile_version": "Перейти на мобильную версию",
|
||||||
"switch_to_desktop_version": "Переключиться на версию для ПК"
|
"switch_to_desktop_version": "Переключиться на версию для ПК",
|
||||||
|
"new-version-available": "Доступно обновление"
|
||||||
},
|
},
|
||||||
"zpetne_odkazy": {
|
"zpetne_odkazy": {
|
||||||
"backlink": "{{count}} ссылки",
|
"backlink": "{{count}} ссылки",
|
||||||
|
|||||||
1
apps/client/src/types.d.ts
vendored
1
apps/client/src/types.d.ts
vendored
@ -26,7 +26,6 @@ interface CustomGlobals {
|
|||||||
appContext: AppContext;
|
appContext: AppContext;
|
||||||
froca: Froca;
|
froca: Froca;
|
||||||
treeCache: Froca;
|
treeCache: Froca;
|
||||||
importMarkdownInline: () => Promise<unknown>;
|
|
||||||
SEARCH_HELP_TEXT: string;
|
SEARCH_HELP_TEXT: string;
|
||||||
activeDialog: JQuery<HTMLElement> | null;
|
activeDialog: JQuery<HTMLElement> | null;
|
||||||
componentId: string;
|
componentId: string;
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import utils from "../../services/utils";
|
|||||||
import Modal from "../react/Modal";
|
import Modal from "../react/Modal";
|
||||||
import Button from "../react/Button";
|
import Button from "../react/Button";
|
||||||
import { useTriliumEvent } from "../react/hooks";
|
import { useTriliumEvent } from "../react/hooks";
|
||||||
|
import EditableTextTypeWidget from "../type_widgets/editable_text";
|
||||||
|
|
||||||
interface RenderMarkdownResponse {
|
interface RenderMarkdownResponse {
|
||||||
htmlContent: string;
|
htmlContent: string;
|
||||||
@ -14,39 +15,34 @@ interface RenderMarkdownResponse {
|
|||||||
|
|
||||||
export default function MarkdownImportDialog() {
|
export default function MarkdownImportDialog() {
|
||||||
const markdownImportTextArea = useRef<HTMLTextAreaElement>(null);
|
const markdownImportTextArea = useRef<HTMLTextAreaElement>(null);
|
||||||
|
const [textTypeWidget, setTextTypeWidget] = useState<EditableTextTypeWidget>();
|
||||||
const [ text, setText ] = useState("");
|
const [ text, setText ] = useState("");
|
||||||
const [ shown, setShown ] = useState(false);
|
const [ shown, setShown ] = useState(false);
|
||||||
|
|
||||||
const triggerImport = useCallback(() => {
|
useTriliumEvent("showPasteMarkdownDialog", ({ textTypeWidget }) => {
|
||||||
if (appContext.tabManager.getActiveContextNoteType() !== "text") {
|
setTextTypeWidget(textTypeWidget);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utils.isElectron()) {
|
if (utils.isElectron()) {
|
||||||
const { clipboard } = utils.dynamicRequire("electron");
|
const { clipboard } = utils.dynamicRequire("electron");
|
||||||
const text = clipboard.readText();
|
const text = clipboard.readText();
|
||||||
|
|
||||||
convertMarkdownToHtml(text);
|
convertMarkdownToHtml(text, textTypeWidget);
|
||||||
} else {
|
} else {
|
||||||
setShown(true);
|
setShown(true);
|
||||||
}
|
}
|
||||||
}, []);
|
});
|
||||||
|
|
||||||
useTriliumEvent("importMarkdownInline", triggerImport);
|
|
||||||
useTriliumEvent("pasteMarkdownIntoText", triggerImport);
|
|
||||||
|
|
||||||
async function sendForm() {
|
|
||||||
await convertMarkdownToHtml(text);
|
|
||||||
setText("");
|
|
||||||
setShown(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
className="markdown-import-dialog" title={t("markdown_import.dialog_title")} size="lg"
|
className="markdown-import-dialog" title={t("markdown_import.dialog_title")} size="lg"
|
||||||
footer={<Button className="markdown-import-button" text={t("markdown_import.import_button")} onClick={sendForm} keyboardShortcut="Ctrl+Space" />}
|
footer={<Button className="markdown-import-button" text={t("markdown_import.import_button")} onClick={() => setShown(false)} keyboardShortcut="Ctrl+Enter" />}
|
||||||
onShown={() => markdownImportTextArea.current?.focus()}
|
onShown={() => markdownImportTextArea.current?.focus()}
|
||||||
onHidden={() => setShown(false) }
|
onHidden={async () => {
|
||||||
|
if (textTypeWidget) {
|
||||||
|
await convertMarkdownToHtml(text, textTypeWidget);
|
||||||
|
}
|
||||||
|
setShown(false);
|
||||||
|
setText("");
|
||||||
|
}}
|
||||||
show={shown}
|
show={shown}
|
||||||
>
|
>
|
||||||
<p>{t("markdown_import.modal_body_text")}</p>
|
<p>{t("markdown_import.modal_body_text")}</p>
|
||||||
@ -56,26 +52,17 @@ export default function MarkdownImportDialog() {
|
|||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
if (e.key === "Enter" && e.ctrlKey) {
|
if (e.key === "Enter" && e.ctrlKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
sendForm();
|
setShown(false);
|
||||||
}
|
}
|
||||||
}}></textarea>
|
}}></textarea>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function convertMarkdownToHtml(markdownContent: string) {
|
async function convertMarkdownToHtml(markdownContent: string, textTypeWidget: EditableTextTypeWidget) {
|
||||||
const { htmlContent } = await server.post<RenderMarkdownResponse>("other/render-markdown", { markdownContent });
|
const { htmlContent } = await server.post<RenderMarkdownResponse>("other/render-markdown", { markdownContent });
|
||||||
|
|
||||||
const textEditor = await appContext.tabManager.getActiveContext()?.getTextEditor();
|
await textTypeWidget.addHtmlToEditor(htmlContent);
|
||||||
if (!textEditor) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const viewFragment = textEditor.data.processor.toView(htmlContent);
|
|
||||||
const modelFragment = textEditor.data.toModel(viewFragment);
|
|
||||||
|
|
||||||
textEditor.model.insertContent(modelFragment, textEditor.model.document.selection);
|
|
||||||
textEditor.editing.view.focus();
|
|
||||||
|
|
||||||
toast.showMessage(t("markdown_import.import_success"));
|
toast.showMessage(t("markdown_import.import_success"));
|
||||||
}
|
}
|
||||||
@ -155,6 +155,11 @@ export default class PopupEditorDialog extends Container<BasicWidget> {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Avoid not showing recent notes when creating a new empty tab.
|
||||||
|
if ("noteContext" in data && data.noteContext.ntxId !== "_popup-editor") {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
return super.handleEventInChildren(name, data);
|
return super.handleEventInChildren(name, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -147,6 +147,12 @@ const categories: Category[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const icons: Icon[] = [
|
const icons: Icon[] = [
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
slug: "empty",
|
||||||
|
category_id: 113,
|
||||||
|
type_of_icon: "REGULAR"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "child",
|
name: "child",
|
||||||
slug: "child-regular",
|
slug: "child-regular",
|
||||||
|
|||||||
@ -56,4 +56,16 @@
|
|||||||
|
|
||||||
.note-icon-widget .icon-list span:hover {
|
.note-icon-widget .icon-list span:hover {
|
||||||
border: 1px solid var(--main-border-color);
|
border: 1px solid var(--main-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-icon-widget .icon-list span.bx-empty {
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-icon-widget .icon-list span.bx-empty::before {
|
||||||
|
display: inline-block;
|
||||||
|
content: "";
|
||||||
|
border: 1px dashed var(--muted-text-color);
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
}
|
}
|
||||||
@ -264,7 +264,6 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
inset-inline-end: 5px;
|
inset-inline-end: 5px;
|
||||||
bottom: 5px;
|
bottom: 5px;
|
||||||
z-index: 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.style-resolver {
|
.style-resolver {
|
||||||
|
|||||||
@ -329,6 +329,30 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addHtmlToEditor(html: string) {
|
||||||
|
await this.initialized;
|
||||||
|
|
||||||
|
const editor = this.watchdog.editor;
|
||||||
|
if (!editor) return;
|
||||||
|
|
||||||
|
editor.model.change((writer) => {
|
||||||
|
const viewFragment = editor.data.processor.toView(html);
|
||||||
|
const modelFragment = editor.data.toModel(viewFragment);
|
||||||
|
const insertPosition = editor.model.document.selection.getLastPosition();
|
||||||
|
|
||||||
|
if (insertPosition) {
|
||||||
|
const range = editor.model.insertContent(modelFragment, insertPosition);
|
||||||
|
|
||||||
|
if (range) {
|
||||||
|
writer.setSelection(range.end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.editing.view.focus();
|
||||||
|
}
|
||||||
|
|
||||||
addTextToActiveEditorEvent({ text }: EventData<"addTextToActiveEditor">) {
|
addTextToActiveEditorEvent({ text }: EventData<"addTextToActiveEditor">) {
|
||||||
if (!this.isActive()) {
|
if (!this.isActive()) {
|
||||||
return;
|
return;
|
||||||
@ -385,6 +409,10 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
this.triggerCommand("showAddLinkDialog", { textTypeWidget: this, text: selectedText });
|
this.triggerCommand("showAddLinkDialog", { textTypeWidget: this, text: selectedText });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pasteMarkdownIntoTextCommand() {
|
||||||
|
this.triggerCommand("showPasteMarkdownDialog", { textTypeWidget: this });
|
||||||
|
}
|
||||||
|
|
||||||
getSelectedText() {
|
getSelectedText() {
|
||||||
const range = this.watchdog.editor?.model.document.selection.getFirstRange();
|
const range = this.watchdog.editor?.model.document.selection.getFirstRange();
|
||||||
let text = "";
|
let text = "";
|
||||||
|
|||||||
@ -6,7 +6,7 @@ WHERE powershell.exe > NUL 2>&1
|
|||||||
IF %ERRORLEVEL% NEQ 0 GOTO BATCH ELSE GOTO POWERSHELL
|
IF %ERRORLEVEL% NEQ 0 GOTO BATCH ELSE GOTO POWERSHELL
|
||||||
|
|
||||||
:POWERSHELL
|
:POWERSHELL
|
||||||
powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo "Set-Item -Path Env:NODE_TLS_REJECT_UNAUTHORIZED -Value 0; ./trilium.exe"
|
powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo -Command "Set-Item -Path Env:NODE_TLS_REJECT_UNAUTHORIZED -Value 0; ./trilium.exe"
|
||||||
GOTO END
|
GOTO END
|
||||||
|
|
||||||
:BATCH
|
:BATCH
|
||||||
|
|||||||
@ -6,7 +6,7 @@ WHERE powershell.exe > NUL 2>&1
|
|||||||
IF %ERRORLEVEL% NEQ 0 GOTO BATCH ELSE GOTO POWERSHELL
|
IF %ERRORLEVEL% NEQ 0 GOTO BATCH ELSE GOTO POWERSHELL
|
||||||
|
|
||||||
:POWERSHELL
|
:POWERSHELL
|
||||||
powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo "Set-Item -Path Env:TRILIUM_DATA_DIR -Value './trilium-data'; ./trilium.exe"
|
powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo -Command "Set-Item -Path Env:TRILIUM_DATA_DIR -Value './trilium-data'; ./trilium.exe"
|
||||||
GOTO END
|
GOTO END
|
||||||
|
|
||||||
:BATCH
|
:BATCH
|
||||||
|
|||||||
@ -6,7 +6,7 @@ WHERE powershell.exe > NUL 2>&1
|
|||||||
IF %ERRORLEVEL% NEQ 0 GOTO BATCH ELSE GOTO POWERSHELL
|
IF %ERRORLEVEL% NEQ 0 GOTO BATCH ELSE GOTO POWERSHELL
|
||||||
|
|
||||||
:POWERSHELL
|
:POWERSHELL
|
||||||
powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo "Set-Item -Path Env:TRILIUM_SAFE_MODE -Value 1; ./trilium.exe --disable-gpu"
|
powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo -Command "Set-Item -Path Env:TRILIUM_SAFE_MODE -Value 1; ./trilium.exe --disable-gpu"
|
||||||
GOTO END
|
GOTO END
|
||||||
|
|
||||||
:BATCH
|
:BATCH
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
"@triliumnext/commons": "workspace:*",
|
"@triliumnext/commons": "workspace:*",
|
||||||
"@triliumnext/server": "workspace:*",
|
"@triliumnext/server": "workspace:*",
|
||||||
"copy-webpack-plugin": "13.0.1",
|
"copy-webpack-plugin": "13.0.1",
|
||||||
"electron": "38.3.0",
|
"electron": "38.4.0",
|
||||||
"@electron-forge/cli": "7.10.2",
|
"@electron-forge/cli": "7.10.2",
|
||||||
"@electron-forge/maker-deb": "7.10.2",
|
"@electron-forge/maker-deb": "7.10.2",
|
||||||
"@electron-forge/maker-dmg": "7.10.2",
|
"@electron-forge/maker-dmg": "7.10.2",
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/better-sqlite3": "7.6.13",
|
"@types/better-sqlite3": "7.6.13",
|
||||||
"@types/mime-types": "3.0.1",
|
"@types/mime-types": "3.0.1",
|
||||||
"@types/yargs": "17.0.33"
|
"@types/yargs": "17.0.34"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tsx src/main.ts",
|
"dev": "tsx src/main.ts",
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
"@triliumnext/desktop": "workspace:*",
|
"@triliumnext/desktop": "workspace:*",
|
||||||
"@types/fs-extra": "11.0.4",
|
"@types/fs-extra": "11.0.4",
|
||||||
"copy-webpack-plugin": "13.0.1",
|
"copy-webpack-plugin": "13.0.1",
|
||||||
"electron": "38.3.0",
|
"electron": "38.4.0",
|
||||||
"fs-extra": "11.3.2"
|
"fs-extra": "11.3.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:22.20.0-bullseye-slim AS builder
|
FROM node:24.10.0-bullseye-slim AS builder
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
# Install native dependencies since we might be building cross-platform.
|
# Install native dependencies since we might be building cross-platform.
|
||||||
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
|||||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||||
|
|
||||||
FROM node:22.20.0-bullseye-slim
|
FROM node:24.10.0-bullseye-slim
|
||||||
# Install only runtime dependencies
|
# Install only runtime dependencies
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:22.20.0-alpine AS builder
|
FROM node:24.10.0-alpine AS builder
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
# Install native dependencies since we might be building cross-platform.
|
# Install native dependencies since we might be building cross-platform.
|
||||||
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
|||||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||||
|
|
||||||
FROM node:22.20.0-alpine
|
FROM node:24.10.0-alpine
|
||||||
# Install runtime dependencies
|
# Install runtime dependencies
|
||||||
RUN apk add --no-cache su-exec shadow
|
RUN apk add --no-cache su-exec shadow
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:22.20.0-alpine AS builder
|
FROM node:24.10.0-alpine AS builder
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
# Install native dependencies since we might be building cross-platform.
|
# Install native dependencies since we might be building cross-platform.
|
||||||
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
|||||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||||
|
|
||||||
FROM node:22.20.0-alpine
|
FROM node:24.10.0-alpine
|
||||||
# Create a non-root user with configurable UID/GID
|
# Create a non-root user with configurable UID/GID
|
||||||
ARG USER=trilium
|
ARG USER=trilium
|
||||||
ARG UID=1001
|
ARG UID=1001
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:22.20.0-bullseye-slim AS builder
|
FROM node:24.10.0-bullseye-slim AS builder
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
# Install native dependencies since we might be building cross-platform.
|
# Install native dependencies since we might be building cross-platform.
|
||||||
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
|||||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||||
|
|
||||||
FROM node:22.20.0-bullseye-slim
|
FROM node:24.10.0-bullseye-slim
|
||||||
# Create a non-root user with configurable UID/GID
|
# Create a non-root user with configurable UID/GID
|
||||||
ARG USER=trilium
|
ARG USER=trilium
|
||||||
ARG UID=1001
|
ARG UID=1001
|
||||||
|
|||||||
@ -37,11 +37,11 @@
|
|||||||
"@triliumnext/express-partial-content": "workspace:*",
|
"@triliumnext/express-partial-content": "workspace:*",
|
||||||
"@triliumnext/turndown-plugin-gfm": "workspace:*",
|
"@triliumnext/turndown-plugin-gfm": "workspace:*",
|
||||||
"@triliumnext/highlightjs": "workspace:*",
|
"@triliumnext/highlightjs": "workspace:*",
|
||||||
"@types/archiver": "6.0.3",
|
"@types/archiver": "7.0.0",
|
||||||
"@types/better-sqlite3": "7.6.13",
|
"@types/better-sqlite3": "7.6.13",
|
||||||
"@types/cls-hooked": "4.3.9",
|
"@types/cls-hooked": "4.3.9",
|
||||||
"@types/compression": "1.8.1",
|
"@types/compression": "1.8.1",
|
||||||
"@types/cookie-parser": "1.4.9",
|
"@types/cookie-parser": "1.4.10",
|
||||||
"@types/debounce": "1.2.4",
|
"@types/debounce": "1.2.4",
|
||||||
"@types/ejs": "3.1.5",
|
"@types/ejs": "3.1.5",
|
||||||
"@types/escape-html": "1.0.4",
|
"@types/escape-html": "1.0.4",
|
||||||
@ -57,18 +57,17 @@
|
|||||||
"@types/sanitize-html": "2.16.0",
|
"@types/sanitize-html": "2.16.0",
|
||||||
"@types/sax": "1.2.7",
|
"@types/sax": "1.2.7",
|
||||||
"@types/serve-favicon": "2.5.7",
|
"@types/serve-favicon": "2.5.7",
|
||||||
"@types/serve-static": "1.15.9",
|
"@types/serve-static": "2.2.0",
|
||||||
"@types/session-file-store": "1.2.5",
|
|
||||||
"@types/stream-throttle": "0.1.4",
|
"@types/stream-throttle": "0.1.4",
|
||||||
"@types/supertest": "6.0.3",
|
"@types/supertest": "6.0.3",
|
||||||
"@types/swagger-ui-express": "4.1.8",
|
"@types/swagger-ui-express": "4.1.8",
|
||||||
"@types/tmp": "0.2.6",
|
"@types/tmp": "0.2.6",
|
||||||
"@types/turndown": "5.0.5",
|
"@types/turndown": "5.0.6",
|
||||||
"@types/ws": "8.18.1",
|
"@types/ws": "8.18.1",
|
||||||
"@types/xml2js": "0.4.14",
|
"@types/xml2js": "0.4.14",
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"async-mutex": "0.5.0",
|
"async-mutex": "0.5.0",
|
||||||
"axios": "1.12.2",
|
"axios": "1.13.0",
|
||||||
"bindings": "1.5.0",
|
"bindings": "1.5.0",
|
||||||
"bootstrap": "5.3.8",
|
"bootstrap": "5.3.8",
|
||||||
"chardet": "2.1.0",
|
"chardet": "2.1.0",
|
||||||
@ -82,7 +81,7 @@
|
|||||||
"debounce": "2.2.0",
|
"debounce": "2.2.0",
|
||||||
"debug": "4.4.3",
|
"debug": "4.4.3",
|
||||||
"ejs": "3.1.10",
|
"ejs": "3.1.10",
|
||||||
"electron": "38.3.0",
|
"electron": "38.4.0",
|
||||||
"electron-debug": "4.1.0",
|
"electron-debug": "4.1.0",
|
||||||
"electron-window-state": "5.0.3",
|
"electron-window-state": "5.0.3",
|
||||||
"escape-html": "1.0.3",
|
"escape-html": "1.0.3",
|
||||||
@ -101,7 +100,7 @@
|
|||||||
"i18next": "25.6.0",
|
"i18next": "25.6.0",
|
||||||
"i18next-fs-backend": "2.6.0",
|
"i18next-fs-backend": "2.6.0",
|
||||||
"image-type": "6.0.0",
|
"image-type": "6.0.0",
|
||||||
"ini": "5.0.0",
|
"ini": "6.0.0",
|
||||||
"is-animated": "2.0.2",
|
"is-animated": "2.0.2",
|
||||||
"is-svg": "6.1.0",
|
"is-svg": "6.1.0",
|
||||||
"jimp": "1.6.0",
|
"jimp": "1.6.0",
|
||||||
@ -111,7 +110,7 @@
|
|||||||
"multer": "2.0.2",
|
"multer": "2.0.2",
|
||||||
"normalize-strings": "1.1.1",
|
"normalize-strings": "1.1.1",
|
||||||
"ollama": "0.6.0",
|
"ollama": "0.6.0",
|
||||||
"openai": "6.6.0",
|
"openai": "6.7.0",
|
||||||
"rand-token": "1.0.1",
|
"rand-token": "1.0.1",
|
||||||
"safe-compare": "1.1.4",
|
"safe-compare": "1.1.4",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
@ -126,9 +125,9 @@
|
|||||||
"swagger-ui-express": "5.0.1",
|
"swagger-ui-express": "5.0.1",
|
||||||
"time2fa": "1.4.2",
|
"time2fa": "1.4.2",
|
||||||
"tmp": "0.2.5",
|
"tmp": "0.2.5",
|
||||||
"turndown": "7.2.1",
|
"turndown": "7.2.2",
|
||||||
"unescape": "1.0.1",
|
"unescape": "1.0.1",
|
||||||
"vite": "7.1.11",
|
"vite": "7.1.12",
|
||||||
"ws": "8.18.3",
|
"ws": "8.18.3",
|
||||||
"xml2js": "0.6.2",
|
"xml2js": "0.6.2",
|
||||||
"yauzl": "3.2.0"
|
"yauzl": "3.2.0"
|
||||||
|
|||||||
@ -84,7 +84,9 @@
|
|||||||
"show-backend-log": "فتح صفحة \"سجل الخلفية\"",
|
"show-backend-log": "فتح صفحة \"سجل الخلفية\"",
|
||||||
"edit-readonly-note": "تعديل ملاحظة القراءة فقط",
|
"edit-readonly-note": "تعديل ملاحظة القراءة فقط",
|
||||||
"attributes-labels-and-relations": "سمات ( تسميات و علاقات)",
|
"attributes-labels-and-relations": "سمات ( تسميات و علاقات)",
|
||||||
"render-active-note": "عرض ( اعادة عرض) الملاحظة المؤرشفة"
|
"render-active-note": "عرض ( اعادة عرض) الملاحظة المؤرشفة",
|
||||||
|
"show-help": "فتح دليل التعليمات",
|
||||||
|
"copy-without-formatting": "نسخ النص المحدد بدون تنسيق"
|
||||||
},
|
},
|
||||||
"setup_sync-from-server": {
|
"setup_sync-from-server": {
|
||||||
"note": "ملاحظة:",
|
"note": "ملاحظة:",
|
||||||
@ -196,7 +198,8 @@
|
|||||||
"expand": "توسيع",
|
"expand": "توسيع",
|
||||||
"site-theme": "المظهر العام للموقع",
|
"site-theme": "المظهر العام للموقع",
|
||||||
"image_alt": "صورة المقال",
|
"image_alt": "صورة المقال",
|
||||||
"on-this-page": "في هذه السفحة"
|
"on-this-page": "في هذه السفحة",
|
||||||
|
"last-updated": "اخر تحديث {{- date}}"
|
||||||
},
|
},
|
||||||
"hidden_subtree_templates": {
|
"hidden_subtree_templates": {
|
||||||
"description": "الوصف",
|
"description": "الوصف",
|
||||||
@ -258,7 +261,8 @@
|
|||||||
},
|
},
|
||||||
"share_page": {
|
"share_page": {
|
||||||
"parent": "الأصل:",
|
"parent": "الأصل:",
|
||||||
"child-notes": "الملاحظات الفرعية:"
|
"child-notes": "الملاحظات الفرعية:",
|
||||||
|
"no-content": "لاتحتوي هذة الملاحظة على محتوى."
|
||||||
},
|
},
|
||||||
"notes": {
|
"notes": {
|
||||||
"duplicate-note-suffix": "(مكرر)",
|
"duplicate-note-suffix": "(مكرر)",
|
||||||
@ -339,7 +343,24 @@
|
|||||||
"toggle-system-tray-icon": "تبديل ايقونة علبة النظام",
|
"toggle-system-tray-icon": "تبديل ايقونة علبة النظام",
|
||||||
"switch-to-first-tab": "التبديل الى التبويب الاول",
|
"switch-to-first-tab": "التبديل الى التبويب الاول",
|
||||||
"follow-link-under-cursor": "اتبع الرابط اسفل المؤشر",
|
"follow-link-under-cursor": "اتبع الرابط اسفل المؤشر",
|
||||||
"paste-markdown-into-text": "لصق نص بتنسبق Markdown"
|
"paste-markdown-into-text": "لصق نص بتنسبق Markdown",
|
||||||
|
"move-note-up-in-hierarchy": "نقل الملاحظة للاعلى في الهيكل",
|
||||||
|
"move-note-down-in-hierarchy": "نقل الملاحظة للاسفل في الهيكل",
|
||||||
|
"select-all-notes-in-parent": "تحديد جميع الملاحظات التابعة للملاحظة الاصل",
|
||||||
|
"add-note-above-to-selection": "اضافة ملاحظة فوق الملاحظة المحددة",
|
||||||
|
"add-note-below-to-selection": "اصافة ملاحظة اسفل الملاحظة المحددة",
|
||||||
|
"add-include-note-to-text": "اضافة الملاحظة الى النص",
|
||||||
|
"toggle-ribbon-tab-image-properties": "اظهار/ اخفاء صورة علامة التبويب في الشريط.",
|
||||||
|
"toggle-ribbon-tab-classic-editor": "عرض/اخفاء تبويب المحور الكلاسيكي",
|
||||||
|
"toggle-ribbon-tab-basic-properties": "عرض/اخفاء تبويب الخصائص الاساسية",
|
||||||
|
"toggle-ribbon-tab-book-properties": "عرض/اخفاء تبويب خصائص الدفتر",
|
||||||
|
"toggle-ribbon-tab-file-properties": "عرض/ادخفاء تبويب خصائص الملف",
|
||||||
|
"toggle-ribbon-tab-owned-attributes": "عرض/اخفاء تبويب المميزات المملوكة",
|
||||||
|
"toggle-ribbon-tab-inherited-attributes": "عرض/اخفاء تبويب السمات الموروثة",
|
||||||
|
"toggle-ribbon-tab-promoted-attributes": "عرض/ اخفاء تبويب السمات المعززة",
|
||||||
|
"toggle-ribbon-tab-note-map": "عرض/اخفاء تبويب خريطة الملاحظات",
|
||||||
|
"toggle-ribbon-tab-similar-notes": "عرض/اخفاء شريط الملاحظات المشابهة",
|
||||||
|
"export-active-note-as-pdf": "تصدير الملاحظة النشطة كملفPDF"
|
||||||
},
|
},
|
||||||
"share_404": {
|
"share_404": {
|
||||||
"title": "غير موجود",
|
"title": "غير موجود",
|
||||||
@ -348,6 +369,7 @@
|
|||||||
"weekdayNumber": "الاسبوع{رقم الاسيوع}",
|
"weekdayNumber": "الاسبوع{رقم الاسيوع}",
|
||||||
"quarterNumber": "الربع {رقم الربع}",
|
"quarterNumber": "الربع {رقم الربع}",
|
||||||
"pdf": {
|
"pdf": {
|
||||||
"export_filter": "مستند PDF (.pdf)"
|
"export_filter": "مستند PDF (.pdf)",
|
||||||
|
"unable-to-export-title": "تعذر التصدير كملف PDF"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -274,7 +274,8 @@
|
|||||||
"export_filter": "PDF Dokument (*.pdf)",
|
"export_filter": "PDF Dokument (*.pdf)",
|
||||||
"unable-to-export-message": "Die aktuelle Notiz konnte nicht als PDF exportiert werden.",
|
"unable-to-export-message": "Die aktuelle Notiz konnte nicht als PDF exportiert werden.",
|
||||||
"unable-to-export-title": "Export als PDF fehlgeschlagen",
|
"unable-to-export-title": "Export als PDF fehlgeschlagen",
|
||||||
"unable-to-save-message": "Die ausgewählte Datei konnte nicht beschrieben werden. Erneut versuchen oder ein anderes Ziel auswählen."
|
"unable-to-save-message": "Die ausgewählte Datei konnte nicht beschrieben werden. Erneut versuchen oder ein anderes Ziel auswählen.",
|
||||||
|
"unable-to-print": "Notiz kann nicht gedruckt werden"
|
||||||
},
|
},
|
||||||
"tray": {
|
"tray": {
|
||||||
"tooltip": "Trilium Notes",
|
"tooltip": "Trilium Notes",
|
||||||
|
|||||||
@ -23,6 +23,14 @@
|
|||||||
"edit-note-title": "Ugrás fáról a jegyzet részleteihez és a cím szerkesztése",
|
"edit-note-title": "Ugrás fáról a jegyzet részleteihez és a cím szerkesztése",
|
||||||
"edit-branch-prefix": "\"Ág címjelzésének szerkesztése\" ablak mutatása",
|
"edit-branch-prefix": "\"Ág címjelzésének szerkesztése\" ablak mutatása",
|
||||||
"clone-notes-to": "Kijelölt jegyzetek másolása",
|
"clone-notes-to": "Kijelölt jegyzetek másolása",
|
||||||
"move-notes-to": "Kijelölt jegyzetek elhelyzése"
|
"move-notes-to": "Kijelölt jegyzetek elhelyzése",
|
||||||
|
"note-clipboard": "Megjegyzés vágólap",
|
||||||
|
"copy-notes-to-clipboard": "Másolja a kiválasztott jegyzeteket a vágólapra",
|
||||||
|
"paste-notes-from-clipboard": "A vágólapról szóló jegyzetek beillesztése aktív jegyzetbe",
|
||||||
|
"cut-notes-to-clipboard": "A kiválasztott jegyzetek kivágása a vágólapra",
|
||||||
|
"select-all-notes-in-parent": "Válassza ki az összes jegyzetet az aktuális jegyzetszintről",
|
||||||
|
"activate-next-tab": "Aktiválja a jobb oldali fület",
|
||||||
|
"activate-previous-tab": "Aktiválja a lapot a bal oldalon",
|
||||||
|
"open-new-window": "Nyiss új üres ablakot"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/src/assets/favicon.ico" />
|
<link rel="icon" type="image/svg+xml" href="/src/assets/favicon.ico" />
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
"test": "vitest",
|
||||||
"preview": "pnpm build && vite preview"
|
"preview": "pnpm build && vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -12,8 +13,8 @@
|
|||||||
"i18next-http-backend": "3.0.2",
|
"i18next-http-backend": "3.0.2",
|
||||||
"preact": "10.27.2",
|
"preact": "10.27.2",
|
||||||
"preact-iso": "2.11.0",
|
"preact-iso": "2.11.0",
|
||||||
"preact-render-to-string": "6.6.2",
|
"preact-render-to-string": "6.6.3",
|
||||||
"react-i18next": "16.1.2"
|
"react-i18next": "16.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@preact/preset-vite": "2.10.2",
|
"@preact/preset-vite": "2.10.2",
|
||||||
@ -21,7 +22,7 @@
|
|||||||
"eslint-config-preact": "2.0.0",
|
"eslint-config-preact": "2.0.0",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"user-agent-data-types": "0.4.2",
|
"user-agent-data-types": "0.4.2",
|
||||||
"vite": "7.1.11"
|
"vite": "7.1.12"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "preact"
|
"extends": "preact"
|
||||||
|
|||||||
BIN
apps/website/public/collection_presentation.webp
Normal file
BIN
apps/website/public/collection_presentation.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"get-started": {
|
|
||||||
"title": "Loslegen",
|
|
||||||
"desktop_title": "Die Desktop-App herunterladen (v{{version}})",
|
|
||||||
"architecture": "Architektur:",
|
|
||||||
"older_releases": "Ältere Releases anzeigen"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
apps/website/src/assets/boxicons/bx-slideshow.svg
Normal file
1
apps/website/src/assets/boxicons/bx-slideshow.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><!--Boxicons v3.0 https://boxicons.com | License https://docs.boxicons.com/free--><path d="M20 3H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h7v3H8v2h8v-2h-3v-3h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2M4 15V5h16v10z"/><path d="m10 13 5-3-5-3z"/></svg>
|
||||||
|
After Width: | Height: | Size: 298 B |
@ -1,7 +1,7 @@
|
|||||||
import { ComponentChildren, HTMLAttributes } from "preact";
|
import { ComponentChildren, HTMLAttributes } from "preact";
|
||||||
import { Link } from "./Button.js";
|
import { Link } from "./Button.js";
|
||||||
import Icon from "./Icon.js";
|
import Icon from "./Icon.js";
|
||||||
import { t } from "../i18n.js";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
||||||
title: ComponentChildren;
|
title: ComponentChildren;
|
||||||
@ -13,6 +13,8 @@ interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Card({ title, children, imageUrl, iconSvg, className, moreInfoUrl, ...restProps }: CardProps) {
|
export default function Card({ title, children, imageUrl, iconSvg, className, moreInfoUrl, ...restProps }: CardProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`card ${className}`} {...restProps}>
|
<div className={`card ${className}`} {...restProps}>
|
||||||
{imageUrl && <img class="image" src={imageUrl} loading="lazy" />}
|
{imageUrl && <img class="image" src={imageUrl} loading="lazy" />}
|
||||||
|
|||||||
@ -3,18 +3,21 @@ import "./DownloadButton.css";
|
|||||||
import Button from "./Button.js";
|
import Button from "./Button.js";
|
||||||
import downloadIcon from "../assets/boxicons/bx-arrow-in-down-square-half.svg?raw";
|
import downloadIcon from "../assets/boxicons/bx-arrow-in-down-square-half.svg?raw";
|
||||||
import packageJson from "../../../../package.json" with { type: "json" };
|
import packageJson from "../../../../package.json" with { type: "json" };
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useContext, useEffect, useState } from "preact/hooks";
|
||||||
import { t } from "../i18n.js";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { LocaleContext } from "../index.js";
|
||||||
|
|
||||||
interface DownloadButtonProps {
|
interface DownloadButtonProps {
|
||||||
big?: boolean;
|
big?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DownloadButton({ big }: DownloadButtonProps) {
|
export default function DownloadButton({ big }: DownloadButtonProps) {
|
||||||
|
const locale = useContext(LocaleContext);
|
||||||
|
const { t } = useTranslation();
|
||||||
const [ recommendedDownload, setRecommendedDownload ] = useState<RecommendedDownload | null>();
|
const [ recommendedDownload, setRecommendedDownload ] = useState<RecommendedDownload | null>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getRecommendedDownload()?.then(setRecommendedDownload);
|
getRecommendedDownload(t)?.then(setRecommendedDownload);
|
||||||
}, []);
|
}, [ t ]);
|
||||||
|
|
||||||
return (recommendedDownload &&
|
return (recommendedDownload &&
|
||||||
<>
|
<>
|
||||||
@ -35,7 +38,7 @@ export default function DownloadButton({ big }: DownloadButtonProps) {
|
|||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
className={`download-button desktop-only ${big ? "big" : ""}`}
|
className={`download-button desktop-only ${big ? "big" : ""}`}
|
||||||
href="/get-started/"
|
href={`/${locale}/get-started/`}
|
||||||
iconSvg={downloadIcon}
|
iconSvg={downloadIcon}
|
||||||
text={<>
|
text={<>
|
||||||
{t("download_now.text")}
|
{t("download_now.text")}
|
||||||
|
|||||||
@ -5,17 +5,26 @@ footer {
|
|||||||
color: var(--muted-color);
|
color: var(--muted-color);
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
|
|
||||||
.content-wrapper {
|
.row {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
gap: 2em;
|
gap: 2em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
|
||||||
@media (min-width: 720px) {
|
@media (min-width: 720px) {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nav.languages {
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5em 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.social-buttons {
|
.social-buttons {
|
||||||
|
|||||||
@ -5,24 +5,46 @@ import githubDiscussionsIcon from "../assets/boxicons/bx-discussion.svg?raw";
|
|||||||
import matrixIcon from "../assets/boxicons/bx-message-dots.svg?raw";
|
import matrixIcon from "../assets/boxicons/bx-message-dots.svg?raw";
|
||||||
import redditIcon from "../assets/boxicons/bx-reddit.svg?raw";
|
import redditIcon from "../assets/boxicons/bx-reddit.svg?raw";
|
||||||
import { Link } from "./Button.js";
|
import { Link } from "./Button.js";
|
||||||
import { t } from "../i18n";
|
import { LOCALES, swapLocaleInUrl } from "../i18n";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useLocation } from "preact-iso";
|
||||||
|
import { useContext } from "preact/hooks";
|
||||||
|
import { LocaleContext } from "..";
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { url } = useLocation();
|
||||||
|
const currentLocale = useContext(LocaleContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer>
|
<footer>
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<div class="footer-text">
|
<div class="row">
|
||||||
© 2024-2025 <Link href="https://github.com/eliandoran" openExternally>Elian Doran</Link>{t("footer.copyright_and_the")}<Link href="https://github.com/TriliumNext/Trilium/graphs/contributors" openExternally>{t("footer.copyright_community")}</Link>.<br />
|
<div class="footer-text">
|
||||||
© 2017-2024 <Link href="https://github.com/zadam" openExternally>zadam</Link>.
|
© 2024-2025 <Link href="https://github.com/eliandoran" openExternally>Elian Doran</Link>{t("footer.copyright_and_the")}<Link href="https://github.com/TriliumNext/Trilium/graphs/contributors" openExternally>{t("footer.copyright_community")}</Link>.<br />
|
||||||
|
© 2017-2024 <Link href="https://github.com/zadam" openExternally>zadam</Link>.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SocialButtons />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SocialButtons />
|
<div class="row">
|
||||||
|
<nav class="languages">
|
||||||
|
{LOCALES.map(locale => (
|
||||||
|
locale.id !== currentLocale
|
||||||
|
? <Link href={swapLocaleInUrl(url, locale.id)}>{locale.name}</Link>
|
||||||
|
: <span className="active">{locale.name}</span>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SocialButtons({ className, withText }: { className?: string, withText?: boolean }) {
|
export function SocialButtons({ className, withText }: { className?: string, withText?: boolean }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`social-buttons ${className}`}>
|
<div className={`social-buttons ${className}`}>
|
||||||
<SocialButton
|
<SocialButton
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
import "./Header.css";
|
import "./Header.css";
|
||||||
import { Link } from "./Button.js";
|
import { Link } from "./Button.js";
|
||||||
import { SocialButtons, SocialButton } from "./Footer.js";
|
import { SocialButtons, SocialButton } from "./Footer.js";
|
||||||
import { useEffect, useMemo, useState } from "preact/hooks";
|
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
||||||
import { useLocation } from 'preact-iso';
|
import { useLocation } from 'preact-iso';
|
||||||
import DownloadButton from './DownloadButton.js';
|
import DownloadButton from './DownloadButton.js';
|
||||||
import githubIcon from "../assets/boxicons/bx-github.svg?raw";
|
import githubIcon from "../assets/boxicons/bx-github.svg?raw";
|
||||||
import Icon from "./Icon.js";
|
import Icon from "./Icon.js";
|
||||||
import logoPath from "../assets/icon-color.svg";
|
import logoPath from "../assets/icon-color.svg";
|
||||||
import menuIcon from "../assets/boxicons/bx-menu.svg?raw";
|
import menuIcon from "../assets/boxicons/bx-menu.svg?raw";
|
||||||
|
import { LocaleContext } from "..";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { swapLocaleInUrl } from "../i18n";
|
||||||
|
|
||||||
interface HeaderLink {
|
interface HeaderLink {
|
||||||
url: string;
|
url: string;
|
||||||
@ -15,21 +18,26 @@ interface HeaderLink {
|
|||||||
external?: boolean;
|
external?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HEADER_LINKS: HeaderLink[] = [
|
|
||||||
{ url: "/get-started/", text: "Get started" },
|
|
||||||
{ url: "https://docs.triliumnotes.org/", text: "Documentation", external: true },
|
|
||||||
{ url: "/support-us/", text: "Support us" }
|
|
||||||
]
|
|
||||||
|
|
||||||
export function Header(props: {repoStargazersCount: number}) {
|
export function Header(props: {repoStargazersCount: number}) {
|
||||||
const { url } = useLocation();
|
const { url } = useLocation();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const locale = useContext(LocaleContext);
|
||||||
const [ mobileMenuShown, setMobileMenuShown ] = useState(false);
|
const [ mobileMenuShown, setMobileMenuShown ] = useState(false);
|
||||||
|
|
||||||
|
const [ headerLinks, setHeaderLinks ] = useState<HeaderLink[]>([]);
|
||||||
|
useEffect(() => {
|
||||||
|
setHeaderLinks([
|
||||||
|
{ url: "/get-started", text: t("header.get-started") },
|
||||||
|
{ url: "https://docs.triliumnotes.org/", text: t("header.documentation"), external: true },
|
||||||
|
{ url: "/support-us", text: t("header.support-us") }
|
||||||
|
]);
|
||||||
|
}, [ locale, t ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header>
|
<header>
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<div class="first-row">
|
<div class="first-row">
|
||||||
<a class="banner" href="/">
|
<a class="banner" href={`/${locale}/`}>
|
||||||
<img src={logoPath} width="300" height="300" alt="Trilium Notes logo" /> <span>Trilium Notes</span>
|
<img src={logoPath} width="300" height="300" alt="Trilium Notes logo" /> <span>Trilium Notes</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -46,16 +54,17 @@ export function Header(props: {repoStargazersCount: number}) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav className={`${mobileMenuShown ? "mobile-shown" : ""}`}>
|
<nav className={`${mobileMenuShown ? "mobile-shown" : ""}`}>
|
||||||
{HEADER_LINKS.map(link => (
|
{headerLinks.map(link => {
|
||||||
<Link
|
const linkHref = link.external ? link.url : swapLocaleInUrl(link.url, locale);
|
||||||
href={link.url}
|
return (<Link
|
||||||
className={url === link.url ? "active" : ""}
|
href={linkHref}
|
||||||
|
className={url === linkHref ? "active" : ""}
|
||||||
openExternally={link.external}
|
openExternally={link.external}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setMobileMenuShown(false);
|
setMobileMenuShown(false);
|
||||||
}}
|
}}
|
||||||
>{link.text}</Link>
|
>{link.text}</Link>)
|
||||||
))}
|
})}
|
||||||
|
|
||||||
<SocialButtons className="mobile-only" withText />
|
<SocialButtons className="mobile-only" withText />
|
||||||
</nav>
|
</nav>
|
||||||
@ -74,4 +83,4 @@ export function Header(props: {repoStargazersCount: number}) {
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
import { TFunction } from 'i18next';
|
||||||
import rootPackageJson from '../../../package.json' with { type: "json" };
|
import rootPackageJson from '../../../package.json' with { type: "json" };
|
||||||
import { t } from './i18n';
|
|
||||||
|
|
||||||
export type App = "desktop" | "server";
|
export type App = "desktop" | "server";
|
||||||
|
|
||||||
@ -34,151 +34,155 @@ export interface RecommendedDownload {
|
|||||||
type DownloadMatrix = Record<App, { [ P in Platform ]?: DownloadMatrixEntry }>;
|
type DownloadMatrix = Record<App, { [ P in Platform ]?: DownloadMatrixEntry }>;
|
||||||
|
|
||||||
// Keep compatibility info inline with https://github.com/electron/electron/blob/main/README.md#platform-support.
|
// Keep compatibility info inline with https://github.com/electron/electron/blob/main/README.md#platform-support.
|
||||||
export const downloadMatrix: DownloadMatrix = {
|
export function getDownloadMatrix(t: TFunction<"translation", undefined>): DownloadMatrix {
|
||||||
desktop: {
|
return {
|
||||||
windows: {
|
desktop: {
|
||||||
title: {
|
windows: {
|
||||||
x64: t("download_helper_desktop_windows.title_x64"),
|
title: {
|
||||||
arm64: t("download_helper_desktop_windows.title_arm64")
|
x64: t("download_helper_desktop_windows.title_x64"),
|
||||||
},
|
arm64: t("download_helper_desktop_windows.title_arm64")
|
||||||
description: {
|
|
||||||
x64: t("download_helper_desktop_windows.description_x64"),
|
|
||||||
arm64: t("download_helper_desktop_windows.description_arm64"),
|
|
||||||
},
|
|
||||||
quickStartTitle: t("download_helper_desktop_windows.quick_start"),
|
|
||||||
quickStartCode: "winget install TriliumNext.Notes",
|
|
||||||
downloads: {
|
|
||||||
exe: {
|
|
||||||
recommended: true,
|
|
||||||
name: t("download_helper_desktop_windows.download_exe")
|
|
||||||
},
|
},
|
||||||
zip: {
|
description: {
|
||||||
name: t("download_helper_desktop_windows.download_zip")
|
x64: t("download_helper_desktop_windows.description_x64"),
|
||||||
|
arm64: t("download_helper_desktop_windows.description_arm64"),
|
||||||
},
|
},
|
||||||
scoop: {
|
quickStartTitle: t("download_helper_desktop_windows.quick_start"),
|
||||||
name: t("download_helper_desktop_windows.download_scoop"),
|
quickStartCode: "winget install TriliumNext.Notes",
|
||||||
url: "https://scoop.sh/#/apps?q=trilium&id=7c08bc3c105b9ee5c00dd4245efdea0f091b8a5c"
|
downloads: {
|
||||||
|
exe: {
|
||||||
|
recommended: true,
|
||||||
|
name: t("download_helper_desktop_windows.download_exe")
|
||||||
|
},
|
||||||
|
zip: {
|
||||||
|
name: t("download_helper_desktop_windows.download_zip")
|
||||||
|
},
|
||||||
|
scoop: {
|
||||||
|
name: t("download_helper_desktop_windows.download_scoop"),
|
||||||
|
url: "https://scoop.sh/#/apps?q=trilium&id=7c08bc3c105b9ee5c00dd4245efdea0f091b8a5c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
linux: {
|
||||||
|
title: {
|
||||||
|
x64: t("download_helper_desktop_linux.title_x64"),
|
||||||
|
arm64: t("download_helper_desktop_linux.title_arm64")
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
x64: t("download_helper_desktop_linux.description_x64"),
|
||||||
|
arm64: t("download_helper_desktop_linux.description_arm64"),
|
||||||
|
},
|
||||||
|
quickStartTitle: t("download_helper_desktop_linux.quick_start"),
|
||||||
|
downloads: {
|
||||||
|
deb: {
|
||||||
|
recommended: true,
|
||||||
|
name: t("download_helper_desktop_linux.download_deb")
|
||||||
|
},
|
||||||
|
rpm: {
|
||||||
|
recommended: true,
|
||||||
|
name: t("download_helper_desktop_linux.download_rpm")
|
||||||
|
},
|
||||||
|
flatpak: {
|
||||||
|
name: t("download_helper_desktop_linux.download_flatpak")
|
||||||
|
},
|
||||||
|
zip: {
|
||||||
|
name: t("download_helper_desktop_linux.download_zip")
|
||||||
|
},
|
||||||
|
nixpkgs: {
|
||||||
|
name: t("download_helper_desktop_linux.download_nixpkgs"),
|
||||||
|
url: "https://search.nixos.org/packages?query=trilium-next"
|
||||||
|
},
|
||||||
|
aur: {
|
||||||
|
name: t("download_helper_desktop_linux.download_aur"),
|
||||||
|
url: "https://aur.archlinux.org/packages/triliumnext-bin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
macos: {
|
||||||
|
title: {
|
||||||
|
x64: t("download_helper_desktop_macos.title_x64"),
|
||||||
|
arm64: t("download_helper_desktop_macos.title_arm64")
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
x64: t("download_helper_desktop_macos.description_x64"),
|
||||||
|
arm64: t("download_helper_desktop_macos.description_arm64"),
|
||||||
|
},
|
||||||
|
quickStartTitle: t("download_helper_desktop_macos.quick_start"),
|
||||||
|
quickStartCode: "brew install --cask trilium-notes",
|
||||||
|
downloads: {
|
||||||
|
dmg: {
|
||||||
|
recommended: true,
|
||||||
|
name: t("download_helper_desktop_macos.download_dmg")
|
||||||
|
},
|
||||||
|
homebrew: {
|
||||||
|
name: t("download_helper_desktop_macos.download_homebrew_cask"),
|
||||||
|
url: "https://formulae.brew.sh/cask/trilium-notes#default"
|
||||||
|
},
|
||||||
|
zip: {
|
||||||
|
name: t("download_helper_desktop_macos.download_zip")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
linux: {
|
server: {
|
||||||
title: {
|
docker: {
|
||||||
x64: t("download_helper_desktop_linux.title_x64"),
|
title: t("download_helper_server_docker.title"),
|
||||||
arm64: t("download_helper_desktop_linux.title_arm64")
|
description: t("download_helper_server_docker.description"),
|
||||||
},
|
helpUrl: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.html",
|
||||||
description: {
|
quickStartCode: "docker pull triliumnext/trilium\ndocker run -p 8080:8080 -d -v ./data:/home/node/trilium-data triliumnext/trilium",
|
||||||
x64: t("download_helper_desktop_linux.description_x64"),
|
downloads: {
|
||||||
arm64: t("download_helper_desktop_linux.description_arm64"),
|
dockerhub: {
|
||||||
},
|
name: t("download_helper_server_docker.download_dockerhub"),
|
||||||
quickStartTitle: t("download_helper_desktop_linux.quick_start"),
|
url: "https://hub.docker.com/r/triliumnext/trilium"
|
||||||
downloads: {
|
},
|
||||||
deb: {
|
ghcr: {
|
||||||
recommended: true,
|
name: t("download_helper_server_docker.download_ghcr"),
|
||||||
name: t("download_helper_desktop_linux.download_deb")
|
url: "https://github.com/TriliumNext/Trilium/pkgs/container/trilium"
|
||||||
},
|
}
|
||||||
rpm: {
|
|
||||||
recommended: true,
|
|
||||||
name: t("download_helper_desktop_linux.download_rpm")
|
|
||||||
},
|
|
||||||
flatpak: {
|
|
||||||
name: t("download_helper_desktop_linux.download_flatpak")
|
|
||||||
},
|
|
||||||
zip: {
|
|
||||||
name: t("download_helper_desktop_linux.download_zip")
|
|
||||||
},
|
|
||||||
nixpkgs: {
|
|
||||||
name: t("download_helper_desktop_linux.download_nixpkgs"),
|
|
||||||
url: "https://search.nixos.org/packages?query=trilium-next"
|
|
||||||
},
|
|
||||||
aur: {
|
|
||||||
name: t("download_helper_desktop_linux.download_aur"),
|
|
||||||
url: "https://aur.archlinux.org/packages/triliumnext-bin"
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
macos: {
|
|
||||||
title: {
|
|
||||||
x64: t("download_helper_desktop_macos.title_x64"),
|
|
||||||
arm64: t("download_helper_desktop_macos.title_arm64")
|
|
||||||
},
|
},
|
||||||
description: {
|
linux: {
|
||||||
x64: t("download_helper_desktop_macos.description_x64"),
|
title: t("download_helper_server_linux.title"),
|
||||||
arm64: t("download_helper_desktop_macos.description_arm64"),
|
description: t("download_helper_server_linux.description"),
|
||||||
|
helpUrl: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/1.%20Installing%20the%20server/Packaged%20version%20for%20Linux.html",
|
||||||
|
downloads: {
|
||||||
|
tarX64: {
|
||||||
|
recommended: true,
|
||||||
|
name: t("download_helper_server_linux.download_tar_x64"),
|
||||||
|
url: `https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-Server-v${version}-linux-x64.tar.xz`,
|
||||||
|
},
|
||||||
|
tarArm64: {
|
||||||
|
recommended: true,
|
||||||
|
name: t("download_helper_server_linux.download_tar_arm64"),
|
||||||
|
url: `https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-Server-v${version}-linux-arm64.tar.xz`
|
||||||
|
},
|
||||||
|
nixos: {
|
||||||
|
name: t("download_helper_server_linux.download_nixos"),
|
||||||
|
url: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/On%20NixOS"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
quickStartTitle: t("download_helper_desktop_macos.quick_start"),
|
pikapod: {
|
||||||
quickStartCode: "brew install --cask trilium-notes",
|
title: t("download_helper_server_hosted.title"),
|
||||||
downloads: {
|
description: t("download_helper_server_hosted.description"),
|
||||||
dmg: {
|
downloads: {
|
||||||
recommended: true,
|
pikapod: {
|
||||||
name: t("download_helper_desktop_macos.download_dmg")
|
recommended: true,
|
||||||
},
|
name: t("download_helper_server_hosted.download_pikapod"),
|
||||||
homebrew: {
|
url: "https://www.pikapods.com/pods?run=trilium-next"
|
||||||
name: t("download_helper_desktop_macos.download_homebrew_cask"),
|
},
|
||||||
url: "https://formulae.brew.sh/cask/trilium-notes#default"
|
triliumcc: {
|
||||||
},
|
name: t("download_helper_server_hosted.download_triliumcc"),
|
||||||
zip: {
|
url: "https://trilium.cc/"
|
||||||
name: t("download_helper_desktop_macos.download_zip")
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
docker: {
|
|
||||||
title: t("download_helper_server_docker.title"),
|
|
||||||
description: t("download_helper_server_docker.description"),
|
|
||||||
helpUrl: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.html",
|
|
||||||
quickStartCode: "docker pull triliumnext/trilium\ndocker run -p 8080:8080 -d -v ./data:/home/node/trilium-data triliumnext/trilium",
|
|
||||||
downloads: {
|
|
||||||
dockerhub: {
|
|
||||||
name: t("download_helper_server_docker.download_dockerhub"),
|
|
||||||
url: "https://hub.docker.com/r/triliumnext/trilium"
|
|
||||||
},
|
|
||||||
ghcr: {
|
|
||||||
name: t("download_helper_server_docker.download_ghcr"),
|
|
||||||
url: "https://github.com/TriliumNext/Trilium/pkgs/container/trilium"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
linux: {
|
|
||||||
title: t("download_helper_server_linux.title"),
|
|
||||||
description: t("download_helper_server_linux.description"),
|
|
||||||
helpUrl: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/1.%20Installing%20the%20server/Packaged%20version%20for%20Linux.html",
|
|
||||||
downloads: {
|
|
||||||
tarX64: {
|
|
||||||
recommended: true,
|
|
||||||
name: t("download_helper_server_linux.download_tar_x64"),
|
|
||||||
url: `https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-Server-v${version}-linux-x64.tar.xz`,
|
|
||||||
},
|
|
||||||
tarArm64: {
|
|
||||||
recommended: true,
|
|
||||||
name: t("download_helper_server_linux.download_tar_arm64"),
|
|
||||||
url: `https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-Server-v${version}-linux-arm64.tar.xz`
|
|
||||||
},
|
|
||||||
nixos: {
|
|
||||||
name: t("download_helper_server_linux.download_nixos"),
|
|
||||||
url: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/On%20NixOS"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pikapod: {
|
|
||||||
title: t("download_helper_server_hosted.title"),
|
|
||||||
description: t("download_helper_server_hosted.description"),
|
|
||||||
downloads: {
|
|
||||||
pikapod: {
|
|
||||||
recommended: true,
|
|
||||||
name: t("download_helper_server_hosted.download_pikapod"),
|
|
||||||
url: "https://www.pikapods.com/pods?run=trilium-next"
|
|
||||||
},
|
|
||||||
triliumcc: {
|
|
||||||
name: t("download_helper_server_hosted.download_triliumcc"),
|
|
||||||
url: "https://trilium.cc/"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function buildDownloadUrl(app: App, platform: Platform, format: string, architecture: Architecture): string {
|
export function buildDownloadUrl(t: TFunction<"translation", undefined>, app: App, platform: Platform, format: string, architecture: Architecture): string {
|
||||||
|
const downloadMatrix = getDownloadMatrix(t);
|
||||||
|
|
||||||
if (app === "desktop") {
|
if (app === "desktop") {
|
||||||
return downloadMatrix.desktop[platform]?.downloads[format].url ??
|
return downloadMatrix.desktop[platform]?.downloads[format].url ??
|
||||||
`https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-v${version}-${platform}-${architecture}.${format}`;
|
`https://github.com/TriliumNext/Trilium/releases/download/v${version}/TriliumNotes-v${version}-${platform}-${architecture}.${format}`;
|
||||||
@ -218,8 +222,9 @@ export function getPlatform(): Platform | null {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRecommendedDownload(): Promise<RecommendedDownload | null> {
|
export async function getRecommendedDownload(t: TFunction<"translation", undefined>): Promise<RecommendedDownload | null> {
|
||||||
if (typeof window === "undefined") return null;
|
if (typeof window === "undefined") return null;
|
||||||
|
const downloadMatrix = getDownloadMatrix(t);
|
||||||
|
|
||||||
const architecture = await getArchitecture();
|
const architecture = await getArchitecture();
|
||||||
const platform = getPlatform();
|
const platform = getPlatform();
|
||||||
@ -233,7 +238,7 @@ export async function getRecommendedDownload(): Promise<RecommendedDownload | nu
|
|||||||
if (!recommendedDownload) return null;
|
if (!recommendedDownload) return null;
|
||||||
|
|
||||||
const format = recommendedDownload[0];
|
const format = recommendedDownload[0];
|
||||||
const url = buildDownloadUrl("desktop", platform, format || 'zip', architecture);
|
const url = buildDownloadUrl(t, "desktop", platform, format || 'zip', architecture);
|
||||||
|
|
||||||
const platformTitle = platformInfo.title;
|
const platformTitle = platformInfo.title;
|
||||||
const name = typeof platformTitle === "string" ? platformTitle : platformTitle[architecture] as string;
|
const name = typeof platformTitle === "string" ? platformTitle : platformTitle[architecture] as string;
|
||||||
|
|||||||
32
apps/website/src/i18n.spec.ts
Normal file
32
apps/website/src/i18n.spec.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { extractLocaleFromUrl, mapLocale, swapLocaleInUrl } from "./i18n";
|
||||||
|
|
||||||
|
describe("mapLocale", () => {
|
||||||
|
it("maps Chinese", () => {
|
||||||
|
expect(mapLocale("zh-TW")).toStrictEqual("zh-Hant");
|
||||||
|
expect(mapLocale("zh-CN")).toStrictEqual("zh-Hans");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("maps languages without countries", () => {
|
||||||
|
expect(mapLocale("ro-RO")).toStrictEqual("ro");
|
||||||
|
expect(mapLocale("ro")).toStrictEqual("ro");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("swapLocale", () => {
|
||||||
|
it("swap locale in URL", () => {
|
||||||
|
expect(swapLocaleInUrl("/get-started", "ro")).toStrictEqual("/ro/get-started");
|
||||||
|
expect(swapLocaleInUrl("/ro/get-started", "ro")).toStrictEqual("/ro/get-started");
|
||||||
|
expect(swapLocaleInUrl("/en/get-started", "ro")).toStrictEqual("/ro/get-started");
|
||||||
|
expect(swapLocaleInUrl("/ro/", "en")).toStrictEqual("/en/");
|
||||||
|
expect(swapLocaleInUrl("/ro", "en")).toStrictEqual("/en");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("extractLocaleFromUrl", () => {
|
||||||
|
it("properly extracts locale", () => {
|
||||||
|
expect(extractLocaleFromUrl("/en/get-started")).toStrictEqual("en");
|
||||||
|
expect(extractLocaleFromUrl("/get-started")).toStrictEqual(undefined);
|
||||||
|
expect(extractLocaleFromUrl("/")).toStrictEqual(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,19 +1,83 @@
|
|||||||
import { default as i18next } from "i18next";
|
import i18next from "i18next";
|
||||||
import HttpApi from 'i18next-http-backend';
|
|
||||||
import { initReactI18next } from "react-i18next";
|
import { initReactI18next } from "react-i18next";
|
||||||
|
|
||||||
i18next
|
interface Locale {
|
||||||
.use(HttpApi)
|
id: string;
|
||||||
.use(initReactI18next);
|
name: string;
|
||||||
|
rtl?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
await i18next.init({
|
i18next.use(initReactI18next);
|
||||||
debug: true,
|
const localeFiles = import.meta.glob("./translations/*/translation.json", { eager: true });
|
||||||
lng: "en",
|
const resources: Record<string, Record<string, Record<string, string>>> = {};
|
||||||
fallbackLng: "en",
|
for (const [path, module] of Object.entries(localeFiles)) {
|
||||||
backend: {
|
const id = path.split("/").at(-2);
|
||||||
loadPath: "/translations/{{lng}}/{{ns}}.json",
|
if (!id) continue;
|
||||||
},
|
|
||||||
returnEmptyString: false
|
|
||||||
});
|
|
||||||
|
|
||||||
export const t = i18next.t;
|
const translations = (module as any).default ?? module;
|
||||||
|
resources[id] = { translation: translations };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initTranslations(lng: string) {
|
||||||
|
i18next.init({
|
||||||
|
fallbackLng: "en",
|
||||||
|
lng,
|
||||||
|
returnEmptyString: false,
|
||||||
|
resources,
|
||||||
|
initAsync: false,
|
||||||
|
react: {
|
||||||
|
useSuspense: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LOCALES: Locale[] = [
|
||||||
|
{ id: "en", name: "English" },
|
||||||
|
{ id: "ro", name: "Română" },
|
||||||
|
{ id: "zh-Hans", name: "简体中文" },
|
||||||
|
{ id: "zh-Hant", name: "繁體中文" },
|
||||||
|
{ id: "fr", name: "Français" },
|
||||||
|
{ id: "it", name: "Italiano" },
|
||||||
|
{ id: "ja", name: "日本語" },
|
||||||
|
{ id: "pl", name: "Polski" },
|
||||||
|
{ id: "es", name: "Español" },
|
||||||
|
{ id: "ar", name: "اَلْعَرَبِيَّةُ", rtl: true },
|
||||||
|
].toSorted((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
export function mapLocale(locale: string) {
|
||||||
|
if (!locale) return 'en';
|
||||||
|
const lower = locale.toLowerCase();
|
||||||
|
|
||||||
|
if (lower.startsWith('zh')) {
|
||||||
|
if (lower.includes('tw') || lower.includes('hk') || lower.includes('mo') || lower.includes('hant')) {
|
||||||
|
return 'zh-Hant';
|
||||||
|
}
|
||||||
|
return 'zh-Hans';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default for everything else
|
||||||
|
return locale.split('-')[0]; // e.g. "en-US" -> "en"
|
||||||
|
}
|
||||||
|
|
||||||
|
export function swapLocaleInUrl(url: string, newLocale: string) {
|
||||||
|
const components = url.split("/");
|
||||||
|
if (components.length === 2) {
|
||||||
|
const potentialLocale = components[1];
|
||||||
|
const correspondingLocale = LOCALES.find(l => l.id === potentialLocale);
|
||||||
|
if (correspondingLocale) {
|
||||||
|
return `/${newLocale}`;
|
||||||
|
} else {
|
||||||
|
return `/${newLocale}${url}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
components[1] = newLocale;
|
||||||
|
return components.join("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function extractLocaleFromUrl(url: string) {
|
||||||
|
const localeId = url.split('/')[1];
|
||||||
|
const correspondingLocale = LOCALES.find(l => l.id === localeId);
|
||||||
|
if (!correspondingLocale) return undefined;
|
||||||
|
return localeId;
|
||||||
|
}
|
||||||
|
|||||||
@ -2,39 +2,92 @@ import './style.css';
|
|||||||
import { FALLBACK_STARGAZERS_COUNT, getRepoStargazersCount } from './github-utils.js';
|
import { FALLBACK_STARGAZERS_COUNT, getRepoStargazersCount } from './github-utils.js';
|
||||||
import { Header } from './components/Header.jsx';
|
import { Header } from './components/Header.jsx';
|
||||||
import { Home } from './pages/Home/index.jsx';
|
import { Home } from './pages/Home/index.jsx';
|
||||||
import { LocationProvider, Router, Route, hydrate, prerender as ssr } from 'preact-iso';
|
import { LocationProvider, Router, Route, hydrate, prerender as ssr, useLocation } from 'preact-iso';
|
||||||
import { NotFound } from './pages/_404.jsx';
|
import { NotFound } from './pages/_404.jsx';
|
||||||
import Footer from './components/Footer.js';
|
import Footer from './components/Footer.js';
|
||||||
import GetStarted from './pages/GetStarted/get-started.js';
|
import GetStarted from './pages/GetStarted/get-started.js';
|
||||||
import SupportUs from './pages/SupportUs/SupportUs.js';
|
import SupportUs from './pages/SupportUs/SupportUs.js';
|
||||||
|
import { createContext } from 'preact';
|
||||||
|
import { useLayoutEffect, useRef } from 'preact/hooks';
|
||||||
|
import { changeLanguage } from 'i18next';
|
||||||
|
import { extractLocaleFromUrl, initTranslations, LOCALES, mapLocale } from './i18n';
|
||||||
|
|
||||||
|
export const LocaleContext = createContext('en');
|
||||||
|
|
||||||
export function App(props: {repoStargazersCount: number}) {
|
export function App(props: {repoStargazersCount: number}) {
|
||||||
return (
|
return (
|
||||||
<LocationProvider>
|
<LocationProvider>
|
||||||
<Header repoStargazersCount={props.repoStargazersCount} />
|
<LocaleProvider>
|
||||||
<main>
|
<Header repoStargazersCount={props.repoStargazersCount} />
|
||||||
<Router>
|
<main>
|
||||||
<Route path="/" component={Home} />
|
<Router>
|
||||||
<Route default component={NotFound} />
|
<Route path="/" component={Home} />
|
||||||
<Route path="/get-started" component={GetStarted} />
|
<Route path="/get-started" component={GetStarted} />
|
||||||
<Route path="/support-us" component={SupportUs} />
|
<Route path="/support-us" component={SupportUs} />
|
||||||
</Router>
|
|
||||||
</main>
|
<Route path="/:locale:/" component={Home} />
|
||||||
<Footer />
|
<Route path="/:locale:/get-started" component={GetStarted} />
|
||||||
|
<Route path="/:locale:/support-us" component={SupportUs} />
|
||||||
|
|
||||||
|
<Route default component={NotFound} />
|
||||||
|
</Router>
|
||||||
|
</main>
|
||||||
|
<Footer />
|
||||||
|
</LocaleProvider>
|
||||||
</LocationProvider>
|
</LocationProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function LocaleProvider({ children }) {
|
||||||
|
const { path } = useLocation();
|
||||||
|
const localeId = getLocaleId(path);
|
||||||
|
const loadedRef = useRef(false);
|
||||||
|
|
||||||
|
if (!loadedRef.current) {
|
||||||
|
initTranslations(localeId);
|
||||||
|
loadedRef.current = true;
|
||||||
|
} else {
|
||||||
|
changeLanguage(localeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update html lang and dir attributes
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const correspondingLocale = LOCALES.find(l => l.id === localeId);
|
||||||
|
document.documentElement.lang = localeId;
|
||||||
|
document.documentElement.dir = correspondingLocale?.rtl ? "rtl" : "ltr";
|
||||||
|
}, [localeId]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LocaleContext.Provider value={localeId}>
|
||||||
|
{children}
|
||||||
|
</LocaleContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
hydrate(<App repoStargazersCount={FALLBACK_STARGAZERS_COUNT} />, document.getElementById('app')!);
|
hydrate(<App repoStargazersCount={FALLBACK_STARGAZERS_COUNT} />, document.getElementById('app')!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLocaleId(path: string) {
|
||||||
|
const extractedLocale = extractLocaleFromUrl(path);
|
||||||
|
if (extractedLocale) return mapLocale(extractedLocale);
|
||||||
|
if (typeof window === "undefined") return 'en';
|
||||||
|
return mapLocale(navigator.language);
|
||||||
|
}
|
||||||
|
|
||||||
export async function prerender(data) {
|
export async function prerender(data) {
|
||||||
// Fetch the stargazer count of the Trilium's GitHub repo on prerender to pass
|
// Fetch the stargazer count of the Trilium's GitHub repo on prerender to pass
|
||||||
// it to the App component for SSR.
|
// it to the App component for SSR.
|
||||||
// This ensures the GitHub API is not called on every page load in the client.
|
// This ensures the GitHub API is not called on every page load in the client.
|
||||||
const stargazersCount = await getRepoStargazersCount();
|
const stargazersCount = await getRepoStargazersCount();
|
||||||
|
|
||||||
return await ssr(<App repoStargazersCount={stargazersCount} {...data} />);
|
const { html, links } = await ssr(<App repoStargazersCount={stargazersCount} {...data} />);
|
||||||
|
return {
|
||||||
|
html,
|
||||||
|
links,
|
||||||
|
head: {
|
||||||
|
lang: extractLocaleFromUrl(data.url) ?? "en"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,20 @@
|
|||||||
import { useLayoutEffect, useState } from "preact/hooks";
|
import { useLayoutEffect, useState } from "preact/hooks";
|
||||||
import Card from "../../components/Card.js";
|
import Card from "../../components/Card.js";
|
||||||
import Section from "../../components/Section.js";
|
import Section from "../../components/Section.js";
|
||||||
import { App, Architecture, buildDownloadUrl, downloadMatrix, DownloadMatrixEntry, getArchitecture, getPlatform, Platform } from "../../download-helper.js";
|
import { App, Architecture, buildDownloadUrl, DownloadMatrixEntry, getArchitecture, getDownloadMatrix, getPlatform, Platform } from "../../download-helper.js";
|
||||||
import { usePageTitle } from "../../hooks.js";
|
import { usePageTitle } from "../../hooks.js";
|
||||||
import Button, { Link } from "../../components/Button.js";
|
import Button, { Link } from "../../components/Button.js";
|
||||||
import Icon from "../../components/Icon.js";
|
import Icon from "../../components/Icon.js";
|
||||||
import helpIcon from "../../assets/boxicons/bx-help-circle.svg?raw";
|
import helpIcon from "../../assets/boxicons/bx-help-circle.svg?raw";
|
||||||
import "./get-started.css";
|
import "./get-started.css";
|
||||||
import packageJson from "../../../../../package.json" with { type: "json" };
|
import packageJson from "../../../../../package.json" with { type: "json" };
|
||||||
import { t } from "../../i18n.js";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export default function DownloadPage() {
|
export default function DownloadPage() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [ currentArch, setCurrentArch ] = useState<Architecture>("x64");
|
const [ currentArch, setCurrentArch ] = useState<Architecture>("x64");
|
||||||
const [ userPlatform, setUserPlatform ] = useState<Platform>();
|
const [ userPlatform, setUserPlatform ] = useState<Platform>();
|
||||||
|
const downloadMatrix = getDownloadMatrix(t);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
getArchitecture().then((arch) => setCurrentArch(arch ?? "x64"));
|
getArchitecture().then((arch) => setCurrentArch(arch ?? "x64"));
|
||||||
@ -71,6 +73,7 @@ export function DownloadCard({ app, arch, entry: [ platform, entry ], isRecommen
|
|||||||
return (typeof text === "string" ? text : text[arch]);
|
return (typeof text === "string" ? text : text[arch]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { t } = useTranslation();
|
||||||
const allDownloads = Object.entries(entry.downloads);
|
const allDownloads = Object.entries(entry.downloads);
|
||||||
const recommendedDownloads = allDownloads.filter(download => download[1].recommended);
|
const recommendedDownloads = allDownloads.filter(download => download[1].recommended);
|
||||||
const restDownloads = allDownloads.filter(download => !download[1].recommended);
|
const restDownloads = allDownloads.filter(download => !download[1].recommended);
|
||||||
@ -107,7 +110,7 @@ export function DownloadCard({ app, arch, entry: [ platform, entry ], isRecommen
|
|||||||
{recommendedDownloads.map(recommendedDownload => (
|
{recommendedDownloads.map(recommendedDownload => (
|
||||||
<Button
|
<Button
|
||||||
className="recommended"
|
className="recommended"
|
||||||
href={buildDownloadUrl(app, platform as Platform, recommendedDownload[0], arch)}
|
href={buildDownloadUrl(t, app, platform as Platform, recommendedDownload[0], arch)}
|
||||||
text={recommendedDownload[1].name}
|
text={recommendedDownload[1].name}
|
||||||
openExternally={!!recommendedDownload[1].url}
|
openExternally={!!recommendedDownload[1].url}
|
||||||
/>
|
/>
|
||||||
@ -117,7 +120,7 @@ export function DownloadCard({ app, arch, entry: [ platform, entry ], isRecommen
|
|||||||
<div class="other-options">
|
<div class="other-options">
|
||||||
{restDownloads.map(download => (
|
{restDownloads.map(download => (
|
||||||
<Link
|
<Link
|
||||||
href={buildDownloadUrl(app, platform as Platform, download[0], arch)}
|
href={buildDownloadUrl(t, app, platform as Platform, download[0], arch)}
|
||||||
openExternally={!!download[1].url}
|
openExternally={!!download[1].url}
|
||||||
>
|
>
|
||||||
{download[1].name}
|
{download[1].name}
|
||||||
|
|||||||
@ -57,6 +57,8 @@ section.hero-section {
|
|||||||
color: transparent;
|
color: transparent;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
font-size: 2em;
|
||||||
|
margin-block: 0.65em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,72 +183,43 @@ section.faq {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: var(--brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
gap: 1em;
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
@media (min-width: 720px) {
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
margin-bottom: 1em;
|
margin: 0;
|
||||||
|
|
||||||
&:last-of-type {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
height: 100%;
|
||||||
|
}
|
||||||
&.selected .card {
|
|
||||||
border: 1px solid var(--brand-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.details {
|
.details {
|
||||||
flex-basis: 50%;
|
max-height: 35vh;
|
||||||
flex-shrink: 0;
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
@media (max-width: 719px) {
|
@media (max-width: 719px) {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.horizontal {
|
img {
|
||||||
flex-direction: column-reverse;
|
object-fit: contain;
|
||||||
|
|
||||||
ul {
|
|
||||||
gap: 1em;
|
|
||||||
display: grid;
|
|
||||||
|
|
||||||
@media (min-width: 720px) {
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
color: var(--brand-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.details {
|
|
||||||
max-height: 35vh;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 100%;
|
|
||||||
width: auto;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,10 +29,10 @@ import calendarIcon from "../../assets/boxicons/bx-calendar.svg?raw";
|
|||||||
import tableIcon from "../../assets/boxicons/bx-table.svg?raw";
|
import tableIcon from "../../assets/boxicons/bx-table.svg?raw";
|
||||||
import boardIcon from "../../assets/boxicons/bx-columns-3.svg?raw";
|
import boardIcon from "../../assets/boxicons/bx-columns-3.svg?raw";
|
||||||
import geomapIcon from "../../assets/boxicons/bx-map.svg?raw";
|
import geomapIcon from "../../assets/boxicons/bx-map.svg?raw";
|
||||||
|
import presentationIcon from "../../assets/boxicons/bx-slideshow.svg?raw";
|
||||||
import { getPlatform } from '../../download-helper.js';
|
import { getPlatform } from '../../download-helper.js';
|
||||||
import { useEffect, useState } from 'preact/hooks';
|
import { useEffect, useState } from 'preact/hooks';
|
||||||
import { t } from '../../i18n.js';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Trans } from 'react-i18next';
|
|
||||||
|
|
||||||
export function Home() {
|
export function Home() {
|
||||||
usePageTitle("");
|
usePageTitle("");
|
||||||
@ -52,6 +52,7 @@ export function Home() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function HeroSection() {
|
function HeroSection() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const platform = getPlatform();
|
const platform = getPlatform();
|
||||||
const colorScheme = useColorScheme();
|
const colorScheme = useColorScheme();
|
||||||
const [ screenshotUrl, setScreenshotUrl ] = useState<string>();
|
const [ screenshotUrl, setScreenshotUrl ] = useState<string>();
|
||||||
@ -96,6 +97,7 @@ function HeroSection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function OrganizationBenefitsSection() {
|
function OrganizationBenefitsSection() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Section className="benefits" title={t("organization_benefits.title")}>
|
<Section className="benefits" title={t("organization_benefits.title")}>
|
||||||
@ -110,6 +112,7 @@ function OrganizationBenefitsSection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ProductivityBenefitsSection() {
|
function ProductivityBenefitsSection() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Section className="benefits accented" title={t("productivity_benefits.title")}>
|
<Section className="benefits accented" title={t("productivity_benefits.title")}>
|
||||||
@ -127,9 +130,10 @@ function ProductivityBenefitsSection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function NoteTypesSection() {
|
function NoteTypesSection() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Section className="note-types" title="Multiple ways to represent your information">
|
<Section className="note-types" title={t("note_types.title")}>
|
||||||
<ListWithScreenshot horizontal items={[
|
<ListWithScreenshot items={[
|
||||||
{
|
{
|
||||||
title: t("note_types.text_title"),
|
title: t("note_types.text_title"),
|
||||||
imageUrl: "/type_text.webp",
|
imageUrl: "/type_text.webp",
|
||||||
@ -190,6 +194,7 @@ function NoteTypesSection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ExtensibilityBenefitsSection() {
|
function ExtensibilityBenefitsSection() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Section className="benefits accented" title={t("extensibility_benefits.title")}>
|
<Section className="benefits accented" title={t("extensibility_benefits.title")}>
|
||||||
@ -205,8 +210,9 @@ function ExtensibilityBenefitsSection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CollectionsSection() {
|
function CollectionsSection() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Section className="collections" title="Collections">
|
<Section className="collections" title={t("collections.title")}>
|
||||||
<ListWithScreenshot items={[
|
<ListWithScreenshot items={[
|
||||||
{
|
{
|
||||||
title: t("collections.calendar_title"),
|
title: t("collections.calendar_title"),
|
||||||
@ -235,49 +241,45 @@ function CollectionsSection() {
|
|||||||
imageUrl: "/collection_geomap.webp",
|
imageUrl: "/collection_geomap.webp",
|
||||||
moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Collections/Geo%20Map%20View.html",
|
moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Collections/Geo%20Map%20View.html",
|
||||||
description: t("collections.geomap_description")
|
description: t("collections.geomap_description")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("collections.presentation_title"),
|
||||||
|
iconSvg: presentationIcon,
|
||||||
|
imageUrl: "/collection_presentation.webp",
|
||||||
|
moreInfo: "https://docs.triliumnotes.org/User%20Guide/User%20Guide/Note%20Types/Collections/Presentation%20View.html",
|
||||||
|
description: t("collections.presentation_description")
|
||||||
}
|
}
|
||||||
]} />
|
]} />
|
||||||
</Section>
|
</Section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ListWithScreenshot({ items, horizontal, cardExtra }: {
|
function ListWithScreenshot({ items, cardExtra }: {
|
||||||
items: { title: string, imageUrl: string, description: string, moreInfo: string, iconSvg?: string }[];
|
items: { title: string, imageUrl: string, description: string, moreInfo: string, iconSvg?: string }[];
|
||||||
horizontal?: boolean;
|
|
||||||
cardExtra?: ComponentChildren;
|
cardExtra?: ComponentChildren;
|
||||||
}) {
|
}) {
|
||||||
const [ selectedItem, setSelectedItem ] = useState(items[0]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`list-with-screenshot ${horizontal ? "horizontal" : ""}`}>
|
<div className={`list-with-screenshot`}>
|
||||||
<ul>
|
<ul>
|
||||||
{items.map(item => (
|
{items.map(item => (
|
||||||
<li className={`${item === selectedItem ? "selected" : ""}`}>
|
<li>
|
||||||
<Card
|
<Card
|
||||||
title={item.title}
|
title={item.title}
|
||||||
onMouseEnter={() => setSelectedItem(item)}
|
|
||||||
onClick={() => setSelectedItem(item)}
|
|
||||||
moreInfoUrl={item.moreInfo}
|
moreInfoUrl={item.moreInfo}
|
||||||
iconSvg={item.iconSvg}
|
iconSvg={item.iconSvg}
|
||||||
|
imageUrl={item.imageUrl}
|
||||||
>
|
>
|
||||||
{item.description}
|
{item.description}
|
||||||
</Card>
|
</Card>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div className="details">
|
|
||||||
{selectedItem && (
|
|
||||||
<>
|
|
||||||
<img src={selectedItem.imageUrl} alt={t("components.list_with_screenshot_alt")} loading="lazy" />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function FaqSection() {
|
function FaqSection() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Section className="faq" title={t("faq.title")}>
|
<Section className="faq" title={t("faq.title")}>
|
||||||
<div class="grid-2-cols">
|
<div class="grid-2-cols">
|
||||||
@ -301,6 +303,7 @@ function FaqItem({ question, children }: { question: string; children: Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
function FinalCta() {
|
function FinalCta() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Section className="final-cta accented" title={t("final_cta.title")}>
|
<Section className="final-cta accented" title={t("final_cta.title")}>
|
||||||
<p>{t("final_cta.description")}</p>
|
<p>{t("final_cta.description")}</p>
|
||||||
|
|||||||
@ -6,10 +6,10 @@ import buyMeACoffeeIcon from "../../assets/boxicons/bx-buy-me-a-coffee.svg?raw";
|
|||||||
import Button, { Link } from "../../components/Button.js";
|
import Button, { Link } from "../../components/Button.js";
|
||||||
import Card from "../../components/Card.js";
|
import Card from "../../components/Card.js";
|
||||||
import { usePageTitle } from "../../hooks.js";
|
import { usePageTitle } from "../../hooks.js";
|
||||||
import { t } from "../../i18n.js";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { Trans } from "react-i18next";
|
|
||||||
|
|
||||||
export default function Donate() {
|
export default function Donate() {
|
||||||
|
const { t } = useTranslation();
|
||||||
usePageTitle(t("support_us.title"));
|
usePageTitle(t("support_us.title"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import Section from "../components/Section.js";
|
import Section from "../components/Section.js";
|
||||||
import { usePageTitle } from "../hooks.js";
|
import { usePageTitle } from "../hooks.js";
|
||||||
import { t } from "../i18n.js";
|
|
||||||
import "./_404.css";
|
import "./_404.css";
|
||||||
|
|
||||||
export function NotFound() {
|
export function NotFound() {
|
||||||
|
const { t } = useTranslation();
|
||||||
usePageTitle(t("404.title"));
|
usePageTitle(t("404.title"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -31,7 +31,13 @@ html,
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
|
font-family: Inter,
|
||||||
|
system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial,
|
||||||
|
"Noto Sans", "Noto Sans CJK SC",
|
||||||
|
"Hiragino Sans", "Hiragino Kaku Gothic ProN",
|
||||||
|
"Microsoft YaHei", "Meiryo", "Malgun Gothic",
|
||||||
|
"PingFang SC", "Source Han Sans SC",
|
||||||
|
"Source Han Sans JP", "Source Han Sans KR";
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,8 @@
|
|||||||
},
|
},
|
||||||
"download_helper_server_hosted": {
|
"download_helper_server_hosted": {
|
||||||
"title": "استضافة مدفوعة",
|
"title": "استضافة مدفوعة",
|
||||||
"download_triliumcc": "بدلا من ذلك، راجع trillum. cc"
|
"download_triliumcc": "بدلا من ذلك، راجع trillum. cc",
|
||||||
|
"download_pikapod": "اعدلد على PikaPods"
|
||||||
},
|
},
|
||||||
"get-started": {
|
"get-started": {
|
||||||
"architecture": "المعمارية:",
|
"architecture": "المعمارية:",
|
||||||
@ -22,7 +23,8 @@
|
|||||||
"organization_benefits": {
|
"organization_benefits": {
|
||||||
"title": "تنظيم",
|
"title": "تنظيم",
|
||||||
"note_structure_title": "هيكيلية الملاحظة",
|
"note_structure_title": "هيكيلية الملاحظة",
|
||||||
"hoisting_title": "مساحات العمل والتركيز على الملاحظة"
|
"hoisting_title": "مساحات العمل والتركيز على الملاحظة",
|
||||||
|
"attributes_title": "العلاقات وجداول الملاحظة"
|
||||||
},
|
},
|
||||||
"productivity_benefits": {
|
"productivity_benefits": {
|
||||||
"sync_title": "المزامنة",
|
"sync_title": "المزامنة",
|
||||||
@ -30,7 +32,8 @@
|
|||||||
"protected_notes_title": "الملاحظات المحمية",
|
"protected_notes_title": "الملاحظات المحمية",
|
||||||
"search_title": "البحث القوي",
|
"search_title": "البحث القوي",
|
||||||
"web_clipper_title": "اداة قص الويب",
|
"web_clipper_title": "اداة قص الويب",
|
||||||
"title": "الانتاجية والسلامة"
|
"title": "الانتاجية والسلامة",
|
||||||
|
"jump_to_title": "الاوامر والبحث السريع"
|
||||||
},
|
},
|
||||||
"note_types": {
|
"note_types": {
|
||||||
"canvas_title": "مساحة العمل",
|
"canvas_title": "مساحة العمل",
|
||||||
@ -66,14 +69,16 @@
|
|||||||
"paypal": "PayPal",
|
"paypal": "PayPal",
|
||||||
"title": "ادعمنا",
|
"title": "ادعمنا",
|
||||||
"financial_donations_title": "التبرعات المالية",
|
"financial_donations_title": "التبرعات المالية",
|
||||||
"github_sponsors": "الرعاة على GitHub"
|
"github_sponsors": "الرعاة على GitHub",
|
||||||
|
"buy_me_a_coffee": "Buy Me A Coffee"
|
||||||
},
|
},
|
||||||
"download_helper_desktop_windows": {
|
"download_helper_desktop_windows": {
|
||||||
"download_scoop": "Scoop",
|
"download_scoop": "Scoop",
|
||||||
"download_exe": "تحميل ملف التثبيت (exe.)",
|
"download_exe": "تحميل ملف التثبيت (exe.)",
|
||||||
"title_x64": "ويندوز 64 بت",
|
"title_x64": "ويندوز 64 بت",
|
||||||
"download_zip": "النسخة المحمولة بصيغة zip",
|
"download_zip": "النسخة المحمولة بصيغة zip",
|
||||||
"title_arm64": "نظام ويندوز عاى ARM"
|
"title_arm64": "نظام ويندوز عاى ARM",
|
||||||
|
"quick_start": "للتثبيت باستخدام Winget:"
|
||||||
},
|
},
|
||||||
"download_helper_desktop_linux": {
|
"download_helper_desktop_linux": {
|
||||||
"download_deb": ".deb",
|
"download_deb": ".deb",
|
||||||
@ -112,6 +117,11 @@
|
|||||||
"download_dmg": "تحميل ملف التثبيت (dmg.)",
|
"download_dmg": "تحميل ملف التثبيت (dmg.)",
|
||||||
"download_homebrew_cask": "Homebrew Cask",
|
"download_homebrew_cask": "Homebrew Cask",
|
||||||
"download_zip": "النسخة المحمولة بصيغة zip",
|
"download_zip": "النسخة المحمولة بصيغة zip",
|
||||||
"title_x64": "نظام macOS لاصدار intel"
|
"title_x64": "نظام macOS لاصدار intel",
|
||||||
|
"title_arm64": "نظام macOS لمعالجة اجهزة Apple Silicon",
|
||||||
|
"quick_start": "للتثبيت بواسطة Homebrew:"
|
||||||
|
},
|
||||||
|
"contribute": {
|
||||||
|
"title": "طرق اخرى للمساهمة"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
46
apps/website/src/translations/de/translation.json
Normal file
46
apps/website/src/translations/de/translation.json
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"get-started": {
|
||||||
|
"title": "Loslegen",
|
||||||
|
"desktop_title": "Die Desktop-App herunterladen (v{{version}})",
|
||||||
|
"architecture": "Architektur:",
|
||||||
|
"older_releases": "Ältere Releases anzeigen",
|
||||||
|
"server_title": "Richte einen Server für den Zugriff auf mehreren Geräten ein"
|
||||||
|
},
|
||||||
|
"hero_section": {
|
||||||
|
"github": "GitHub",
|
||||||
|
"get_started": "Loslegen",
|
||||||
|
"dockerhub": "Docker Hub",
|
||||||
|
"title": "Organisieren Sie Ihre Gedanken. Bauen Sie Ihre persönliche Wissensdatenbank auf.",
|
||||||
|
"subtitle": "Trilium ist eine Open-Source-Lösung zum Erstellen von Notizen und Organisieren einer persönlichen Wissensdatenbank. Sie kann lokal auf dem Desktop verwendet oder mit einem selbst gehosteten Server synchronisieren werden, um erstellte Notizen überall verfügbar zu haben.",
|
||||||
|
"screenshot_alt": "Screenshot der Desktop-Anwendung Trilium Notes"
|
||||||
|
},
|
||||||
|
"organization_benefits": {
|
||||||
|
"title": "Organisation",
|
||||||
|
"note_structure_title": "Notizstruktur",
|
||||||
|
"attributes_title": "Notiz Labels und Beziehungen"
|
||||||
|
},
|
||||||
|
"productivity_benefits": {
|
||||||
|
"revisions_title": "Notizrevisionen",
|
||||||
|
"title": "Produktivität und Sicherheit",
|
||||||
|
"sync_title": "Synchronisation",
|
||||||
|
"protected_notes_title": "Geschützte Notizen",
|
||||||
|
"jump_to_title": "Schnellsuche und Kommandos",
|
||||||
|
"search_title": "Leistungsstarke Suche",
|
||||||
|
"web_clipper_title": "Web clipper"
|
||||||
|
},
|
||||||
|
"note_types": {
|
||||||
|
"text_title": "Text Notizen",
|
||||||
|
"code_title": "Code Notizen",
|
||||||
|
"canvas_title": "Canvas",
|
||||||
|
"mermaid_title": "Mermaid Diagramm",
|
||||||
|
"mindmap_title": "Mind Map"
|
||||||
|
},
|
||||||
|
"extensibility_benefits": {
|
||||||
|
"import_export_title": "Import/Export",
|
||||||
|
"scripting_title": "Erweitertes Scripting",
|
||||||
|
"api_title": "REST API"
|
||||||
|
},
|
||||||
|
"collections": {
|
||||||
|
"calendar_title": "Kalender"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,6 +39,7 @@
|
|||||||
"web_clipper_content": "Grab web pages (or screenshots) and place them directly into Trilium using the web clipper browser extension."
|
"web_clipper_content": "Grab web pages (or screenshots) and place them directly into Trilium using the web clipper browser extension."
|
||||||
},
|
},
|
||||||
"note_types": {
|
"note_types": {
|
||||||
|
"title": "Multiple ways to represent your information",
|
||||||
"text_title": "Text notes",
|
"text_title": "Text notes",
|
||||||
"text_description": "The notes are edited using a visual (WYSIWYG) editor, with support for tables, images, math expressions, code blocks with syntax highlighting. Quickly format the text using Markdown-like syntax or using slash commands.",
|
"text_description": "The notes are edited using a visual (WYSIWYG) editor, with support for tables, images, math expressions, code blocks with syntax highlighting. Quickly format the text using Markdown-like syntax or using slash commands.",
|
||||||
"code_title": "Code notes",
|
"code_title": "Code notes",
|
||||||
@ -65,6 +66,7 @@
|
|||||||
"api_description": "Interact with Trilium programatically using its builtin REST API."
|
"api_description": "Interact with Trilium programatically using its builtin REST API."
|
||||||
},
|
},
|
||||||
"collections": {
|
"collections": {
|
||||||
|
"title": "Collections",
|
||||||
"calendar_title": "Calendar",
|
"calendar_title": "Calendar",
|
||||||
"calendar_description": "Organize your personal or professional events using a calendar, with support for all-day and multi-day events. See your events at a glance with the week, month and year views. Easy interaction to add or drag events.",
|
"calendar_description": "Organize your personal or professional events using a calendar, with support for all-day and multi-day events. See your events at a glance with the week, month and year views. Easy interaction to add or drag events.",
|
||||||
"table_title": "Table",
|
"table_title": "Table",
|
||||||
@ -72,7 +74,9 @@
|
|||||||
"board_title": "Board",
|
"board_title": "Board",
|
||||||
"board_description": "Organize your tasks or project status into a Kanban board with an easy way to create new items and columns and simply changing their status by dragging across the board.",
|
"board_description": "Organize your tasks or project status into a Kanban board with an easy way to create new items and columns and simply changing their status by dragging across the board.",
|
||||||
"geomap_title": "Geomap",
|
"geomap_title": "Geomap",
|
||||||
"geomap_description": "Plan your vacations or mark your points of interest directly on a geographical map using customizable markers. Display recorded GPX tracks to track itineraries."
|
"geomap_description": "Plan your vacations or mark your points of interest directly on a geographical map using customizable markers. Display recorded GPX tracks to track itineraries.",
|
||||||
|
"presentation_title": "Presentation",
|
||||||
|
"presentation_description": "Organize information into slides and present them in full-screen with smooth transitions. The slides can also be exported to PDF for easy sharing."
|
||||||
},
|
},
|
||||||
"faq": {
|
"faq": {
|
||||||
"title": "Frequently Asked Questions",
|
"title": "Frequently Asked Questions",
|
||||||
@ -95,8 +99,7 @@
|
|||||||
"get_started": "Get started"
|
"get_started": "Get started"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"link_learn_more": "Learn more...",
|
"link_learn_more": "Learn more..."
|
||||||
"list_with_screenshot_alt": "Screenshot of the feature being selected"
|
|
||||||
},
|
},
|
||||||
"download_now": {
|
"download_now": {
|
||||||
"text": "Download now ",
|
"text": "Download now ",
|
||||||
@ -106,6 +109,11 @@
|
|||||||
"linux_small": "for Linux",
|
"linux_small": "for Linux",
|
||||||
"more_platforms": "More platforms & server setup"
|
"more_platforms": "More platforms & server setup"
|
||||||
},
|
},
|
||||||
|
"header": {
|
||||||
|
"get-started": "Get started",
|
||||||
|
"documentation": "Documentation",
|
||||||
|
"support-us": "Support us"
|
||||||
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"copyright_and_the": " and the ",
|
"copyright_and_the": " and the ",
|
||||||
"copyright_community": "community"
|
"copyright_community": "community"
|
||||||
@ -163,7 +171,7 @@
|
|||||||
"download_helper_desktop_macos": {
|
"download_helper_desktop_macos": {
|
||||||
"title_x64": "macOS for Intel",
|
"title_x64": "macOS for Intel",
|
||||||
"title_arm64": "macOS for Apple Silicon",
|
"title_arm64": "macOS for Apple Silicon",
|
||||||
"description_x64": "For Intel-based Macs running macOS Big Sur or later.",
|
"description_x64": "For Intel-based Macs running macOS Monterey or later.",
|
||||||
"description_arm64": "For Apple Silicon Macs such as those with M1 and M2 chips.",
|
"description_arm64": "For Apple Silicon Macs such as those with M1 and M2 chips.",
|
||||||
"quick_start": "To install via Homebrew:",
|
"quick_start": "To install via Homebrew:",
|
||||||
"download_dmg": "Download Installer (.dmg)",
|
"download_dmg": "Download Installer (.dmg)",
|
||||||
@ -95,8 +95,7 @@
|
|||||||
"get_started": "Comenzar"
|
"get_started": "Comenzar"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"link_learn_more": "Saber más…",
|
"link_learn_more": "Saber más…"
|
||||||
"list_with_screenshot_alt": "Captura de pantalla de la función seleccionada"
|
|
||||||
},
|
},
|
||||||
"download_now": {
|
"download_now": {
|
||||||
"text": "Descarga ahora ",
|
"text": "Descarga ahora ",
|
||||||
@ -163,7 +162,7 @@
|
|||||||
"download_helper_desktop_macos": {
|
"download_helper_desktop_macos": {
|
||||||
"title_x64": "macOS para Intel",
|
"title_x64": "macOS para Intel",
|
||||||
"title_arm64": "macOS para Apple Silicon",
|
"title_arm64": "macOS para Apple Silicon",
|
||||||
"description_x64": "Para Macs con procesador Intel que ejecuten macOS Big Sur o posterior.",
|
"description_x64": "Para Macs con procesador Intel que ejecuten macOS Monterey o posterior.",
|
||||||
"description_arm64": "Para Macs con Apple Silicon, como los que tienen chips M1 y M2.",
|
"description_arm64": "Para Macs con Apple Silicon, como los que tienen chips M1 y M2.",
|
||||||
"quick_start": "Para instalar mediante Homebrew:",
|
"quick_start": "Para instalar mediante Homebrew:",
|
||||||
"download_dmg": "Descargar instalador (.dmg)",
|
"download_dmg": "Descargar instalador (.dmg)",
|
||||||
@ -74,8 +74,7 @@
|
|||||||
"get_started": "Commencer"
|
"get_started": "Commencer"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"link_learn_more": "En savoir plus...",
|
"link_learn_more": "En savoir plus..."
|
||||||
"list_with_screenshot_alt": "Capture d'écran de la fonctionnalité sélectionnée"
|
|
||||||
},
|
},
|
||||||
"support_us": {
|
"support_us": {
|
||||||
"financial_donations_title": "Dons financiers",
|
"financial_donations_title": "Dons financiers",
|
||||||
@ -124,7 +123,7 @@
|
|||||||
"download_helper_desktop_macos": {
|
"download_helper_desktop_macos": {
|
||||||
"title_x64": "macOS pour Intel",
|
"title_x64": "macOS pour Intel",
|
||||||
"title_arm64": "macOS pour Apple Silicon",
|
"title_arm64": "macOS pour Apple Silicon",
|
||||||
"description_x64": "Pour les Mac basés sur Intel exécutant macOS Big Sur ou une version ultérieure.",
|
"description_x64": "Pour les Mac basés sur Intel exécutant macOS Monterey ou une version ultérieure.",
|
||||||
"description_arm64": "Pour les Mac Apple Silicon tels que ceux équipés de puces M1 et M2.",
|
"description_arm64": "Pour les Mac Apple Silicon tels que ceux équipés de puces M1 et M2.",
|
||||||
"quick_start": "Pour installer via Homebrew :",
|
"quick_start": "Pour installer via Homebrew :",
|
||||||
"download_dmg": "Télécharger le programme d'installation (.dmg)",
|
"download_dmg": "Télécharger le programme d'installation (.dmg)",
|
||||||
5
apps/website/src/translations/hi/translation.json
Normal file
5
apps/website/src/translations/hi/translation.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"get-started": {
|
||||||
|
"title": "शुरू करें"
|
||||||
|
}
|
||||||
|
}
|
||||||
44
apps/website/src/translations/hu/translation.json
Normal file
44
apps/website/src/translations/hu/translation.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"get-started": {
|
||||||
|
"title": "Kezdés",
|
||||||
|
"desktop_title": "Töltsd le az asztali alkalmazást (v{{version}})",
|
||||||
|
"architecture": "Szerkezet:",
|
||||||
|
"older_releases": "Régebbi kiadások megtekintése",
|
||||||
|
"server_title": "Szerver beállítása több eszközről történő hozzáféréshez"
|
||||||
|
},
|
||||||
|
"hero_section": {
|
||||||
|
"title": "Rendszerezd a gondolataidat. Építsd fel a személyes tudásbázisodat.",
|
||||||
|
"subtitle": "A Trilium egy nyílt forráskódú megoldás jegyzeteléshez és személyes tudásbázis rendszerezéséhez. Használd helyben az asztali gépeden, vagy szinkronizáld a saját szervereddel, hogy jegyzeteid mindenhol elérhetőek legyenek.",
|
||||||
|
"get_started": "Kezdés",
|
||||||
|
"github": "GitHub",
|
||||||
|
"dockerhub": "Docker Hub",
|
||||||
|
"screenshot_alt": "A Trilium Notes asztali alkalmazás képernyőképe"
|
||||||
|
},
|
||||||
|
"organization_benefits": {
|
||||||
|
"title": "Szervezet",
|
||||||
|
"note_structure_title": "Jegyzet szerkezet",
|
||||||
|
"note_structure_description": "A jegyzetek hierarchikusan rendezhetők. Nincs szükség mappákra, mivel minden jegyzet tartalmazhat aljegyzeteket. Egyetlen jegyzet több helyre is hozzáadható a hierarchiában.",
|
||||||
|
"attributes_title": "Jegyzetcímkék és kapcsolatok",
|
||||||
|
"attributes_description": "Használjon kapcsolatokat a jegyzetek között, vagy adjon hozzá címkéket az egyszerű kategorizálás érdekében. Használjon kiemelt attribútumokat strukturált információk beviteléhez, amelyek táblázatokban és táblákon használhatók.",
|
||||||
|
"hoisting_title": "Munkaterületek és kiemelés",
|
||||||
|
"hoisting_description": "Könnyedén különítse el a személyes és munkahelyi jegyzeteit úgy, hogy csoportosítja őket egy munkaterület alatt, amely a jegyzetfát csak egy adott jegyzetkészlet megjelenítésére összpontosítja."
|
||||||
|
},
|
||||||
|
"productivity_benefits": {
|
||||||
|
"title": "Termelékenység és biztonság",
|
||||||
|
"revisions_title": "Megjegyzés felülvizsgálatai",
|
||||||
|
"revisions_content": "A jegyzetek rendszeresen tárolódnak a háttérben, és a revíziók felhasználhatók felülvizsgálatra vagy véletlen változások visszavonására. A revíziók igény szerint is létrehozhatók.",
|
||||||
|
"sync_title": "Szinkronizálás",
|
||||||
|
"sync_content": "Használjon saját maga által üzemeltetett vagy felhő alapu példányt, hogy könnyen szinkronizálja a jegyzeteket több eszközön keresztül, és hozzáférjen a mobiltelefonjáról egy PWA segítségével.",
|
||||||
|
"protected_notes_title": "Védett jegyzetek",
|
||||||
|
"protected_notes_content": "Védje az érzékeny személyes adatokat a jegyzetek titkosításával és a jelszóval védett munkamenet mögötti zárolással.",
|
||||||
|
"jump_to_title": "Gyors keresés és parancsok",
|
||||||
|
"jump_to_content": "Ugorj gyorsan a jegyzetekhez vagy a felhasználói felület parancsaihoz a hierarchia területén, keresve a címüket, a fuzzy illesztéssel, hogy megmagyarázza az elírásokat vagy az enyhe különbségeket.",
|
||||||
|
"search_title": "Erőteljes keresés",
|
||||||
|
"search_content": "Vagy keressen szöveget a jegyzetekben, és szűkítse le a keresést a szülői jegyzet szűrésével vagy mélységével."
|
||||||
|
},
|
||||||
|
"note_types": {
|
||||||
|
"file_description": "Beágyazott multimédiás fájlokat, például PDF-eket, képeket, videókat, alkalmazáson belüli előnézettel.",
|
||||||
|
"canvas_title": "Vászon",
|
||||||
|
"canvas_description": "Rendezzen formákat, képeket és szöveget egy végtelen vászonra, ugyanazzal a technológiával mint ami excalidraw.com mögött van. Ideális diagramokhoz, vázlatokhoz és vizuális tervezéshez."
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -51,7 +51,8 @@
|
|||||||
"mermaid_description": "Crea diagrammi come diagrammi di flusso, diagrammi di classe e sequenza, diagrammi di Gantt e molti altri, utilizzando la sintassi Mermaid.",
|
"mermaid_description": "Crea diagrammi come diagrammi di flusso, diagrammi di classe e sequenza, diagrammi di Gantt e molti altri, utilizzando la sintassi Mermaid.",
|
||||||
"mindmap_title": "Mappe mentali",
|
"mindmap_title": "Mappe mentali",
|
||||||
"mindmap_description": "Organizza i tuoi pensieri visivamente o fai una sessione di brainstorming.",
|
"mindmap_description": "Organizza i tuoi pensieri visivamente o fai una sessione di brainstorming.",
|
||||||
"others_list": "e altri: <0>mappa delle note</0>, <1>mappa delle relazioni</1>, <2>ricerche salvate</2>, <3>renderizza nota</3> e <4>visualizzazioni web</4>."
|
"others_list": "e altri: <0>mappa delle note</0>, <1>mappa delle relazioni</1>, <2>ricerche salvate</2>, <3>renderizza nota</3> e <4>visualizzazioni web</4>.",
|
||||||
|
"title": "Diversi modi per rappresentare le tue informazioni"
|
||||||
},
|
},
|
||||||
"extensibility_benefits": {
|
"extensibility_benefits": {
|
||||||
"title": "Condivisione ed estensibilità",
|
"title": "Condivisione ed estensibilità",
|
||||||
@ -72,7 +73,10 @@
|
|||||||
"board_title": "Board",
|
"board_title": "Board",
|
||||||
"board_description": "Organizza le tue attività o lo stato dei tuoi progetti in una lavagna Kanban con un modo semplice per creare nuovi elementi e colonne e modificare facilmente il loro stato trascinandoli sulla lavagna.",
|
"board_description": "Organizza le tue attività o lo stato dei tuoi progetti in una lavagna Kanban con un modo semplice per creare nuovi elementi e colonne e modificare facilmente il loro stato trascinandoli sulla lavagna.",
|
||||||
"geomap_title": "Geomappa",
|
"geomap_title": "Geomappa",
|
||||||
"geomap_description": "Pianifica le tue vacanze o segna i tuoi punti di interesse direttamente su una mappa geografica utilizzando indicatori personalizzabili. Visualizza le tracce GPX registrate per seguire gli itinerari."
|
"geomap_description": "Pianifica le tue vacanze o segna i tuoi punti di interesse direttamente su una mappa geografica utilizzando indicatori personalizzabili. Visualizza le tracce GPX registrate per seguire gli itinerari.",
|
||||||
|
"title": "Collezioni",
|
||||||
|
"presentation_title": "Presentazione",
|
||||||
|
"presentation_description": "Organizza le informazioni in diapositive e presentale a schermo intero con transizioni fluide. Le diapositive possono anche essere esportate in formato PDF per una facile condivisione."
|
||||||
},
|
},
|
||||||
"faq": {
|
"faq": {
|
||||||
"title": "Domande frequenti",
|
"title": "Domande frequenti",
|
||||||
@ -95,8 +99,7 @@
|
|||||||
"get_started": "Inizia ora"
|
"get_started": "Inizia ora"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"link_learn_more": "Per saperne di più...",
|
"link_learn_more": "Per saperne di più..."
|
||||||
"list_with_screenshot_alt": "Screenshot della funzione selezionata"
|
|
||||||
},
|
},
|
||||||
"download_now": {
|
"download_now": {
|
||||||
"text": "Scarica ora ",
|
"text": "Scarica ora ",
|
||||||
@ -163,7 +166,7 @@
|
|||||||
"download_helper_desktop_macos": {
|
"download_helper_desktop_macos": {
|
||||||
"title_x64": "macOS per Intel",
|
"title_x64": "macOS per Intel",
|
||||||
"title_arm64": "macOS per Apple Silicon",
|
"title_arm64": "macOS per Apple Silicon",
|
||||||
"description_x64": "Per Mac basati su Intel con macOS Big Sur o versioni successive.",
|
"description_x64": "Per Mac basati su Intel con macOS Monterey o versioni successive.",
|
||||||
"description_arm64": "Per i Mac Apple Silicon, come quelli con chip M1 e M2.",
|
"description_arm64": "Per i Mac Apple Silicon, come quelli con chip M1 e M2.",
|
||||||
"quick_start": "Per installare tramite Homebrew:",
|
"quick_start": "Per installare tramite Homebrew:",
|
||||||
"download_dmg": "Scarica il programma di installazione (.dmg)",
|
"download_dmg": "Scarica il programma di installazione (.dmg)",
|
||||||
@ -188,5 +191,10 @@
|
|||||||
"description": "Trilium Notes è ospitato su PikaPods, un servizio a pagamento che consente un facile accesso e una semplice gestione. Non è direttamente affiliato al team Trilium.",
|
"description": "Trilium Notes è ospitato su PikaPods, un servizio a pagamento che consente un facile accesso e una semplice gestione. Non è direttamente affiliato al team Trilium.",
|
||||||
"download_pikapod": "Configurazione su PikaPods",
|
"download_pikapod": "Configurazione su PikaPods",
|
||||||
"download_triliumcc": "In alternativa, consultare trilium.cc"
|
"download_triliumcc": "In alternativa, consultare trilium.cc"
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"get-started": "Inizia",
|
||||||
|
"documentation": "Documentazione",
|
||||||
|
"support-us": "Sostienici"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,7 +51,8 @@
|
|||||||
"mermaid_description": "Mermaid 構文を使用して、フローチャート、クラス図、シーケンス図、ガント チャートなどの図を作成します。",
|
"mermaid_description": "Mermaid 構文を使用して、フローチャート、クラス図、シーケンス図、ガント チャートなどの図を作成します。",
|
||||||
"mindmap_title": "マインドマップ",
|
"mindmap_title": "マインドマップ",
|
||||||
"mindmap_description": "考えを視覚的に整理したり、ブレインストーミング セッションを行ったりします。",
|
"mindmap_description": "考えを視覚的に整理したり、ブレインストーミング セッションを行ったりします。",
|
||||||
"others_list": "その他: <0>ノートマップ</0>、<1>リレーションマップ</1>、<2>保存された検索</2>、<3>レンダリングノート</3>、<4>Web ビュー</4>。"
|
"others_list": "その他: <0>ノートマップ</0>、<1>リレーションマップ</1>、<2>保存された検索</2>、<3>レンダリングノート</3>、<4>Web ビュー</4>。",
|
||||||
|
"title": "情報を表現するための複数の方法"
|
||||||
},
|
},
|
||||||
"extensibility_benefits": {
|
"extensibility_benefits": {
|
||||||
"title": "共有と拡張性",
|
"title": "共有と拡張性",
|
||||||
@ -72,7 +73,10 @@
|
|||||||
"board_title": "ボード",
|
"board_title": "ボード",
|
||||||
"board_description": "新しい項目や列を簡単に作成し、ボード上でドラッグするだけでステータスを変更できるカンバン ボードで、タスクやプロジェクトのステータスを整理できます。",
|
"board_description": "新しい項目や列を簡単に作成し、ボード上でドラッグするだけでステータスを変更できるカンバン ボードで、タスクやプロジェクトのステータスを整理できます。",
|
||||||
"geomap_title": "ジオマップ",
|
"geomap_title": "ジオマップ",
|
||||||
"geomap_description": "カスタマイズ可能なマーカーを使って、休暇を計画したり、興味のある場所を地図上に直接マークしたりできます。記録されたGPXトラックを表示して、旅程を追跡できます。"
|
"geomap_description": "カスタマイズ可能なマーカーを使って、休暇を計画したり、興味のある場所を地図上に直接マークしたりできます。記録されたGPXトラックを表示して、旅程を追跡できます。",
|
||||||
|
"title": "コレクション",
|
||||||
|
"presentation_title": "プレゼンテーション",
|
||||||
|
"presentation_description": "情報をスライドに整理し、スムーズな遷移で全画面表示できます。スライドはPDFにエクスポートできるので、簡単に共有できます。"
|
||||||
},
|
},
|
||||||
"faq": {
|
"faq": {
|
||||||
"title": "よくある質問",
|
"title": "よくある質問",
|
||||||
@ -95,8 +99,7 @@
|
|||||||
"get_started": "はじめる"
|
"get_started": "はじめる"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"link_learn_more": "さらに詳しく...",
|
"link_learn_more": "さらに詳しく..."
|
||||||
"list_with_screenshot_alt": "選択中の機能のスクリーンショット"
|
|
||||||
},
|
},
|
||||||
"download_now": {
|
"download_now": {
|
||||||
"text": "今すぐダウンロード ",
|
"text": "今すぐダウンロード ",
|
||||||
@ -163,7 +166,7 @@
|
|||||||
"download_helper_desktop_macos": {
|
"download_helper_desktop_macos": {
|
||||||
"title_x64": "Intel 向け macOS",
|
"title_x64": "Intel 向け macOS",
|
||||||
"title_arm64": "Apple Silicon 向け macOS",
|
"title_arm64": "Apple Silicon 向け macOS",
|
||||||
"description_x64": "macOS Big Sur 以降を実行している Intel ベースの Mac 向け。",
|
"description_x64": "macOS Monterey 以降を実行している Intel ベースの Mac 向け。",
|
||||||
"description_arm64": "M1 および M2 チップを搭載した Apple Silicon Mac 向け。",
|
"description_arm64": "M1 および M2 チップを搭載した Apple Silicon Mac 向け。",
|
||||||
"quick_start": "Homebrew 経由でインストールするには:",
|
"quick_start": "Homebrew 経由でインストールするには:",
|
||||||
"download_dmg": "インストーラーをダウンロード (.dmg)",
|
"download_dmg": "インストーラーをダウンロード (.dmg)",
|
||||||
@ -188,5 +191,10 @@
|
|||||||
"description": "Trilium Notesは、アクセスと管理を容易にする有料サービス PikaPods でホストされています。Trilium チームとは直接関係ありません。",
|
"description": "Trilium Notesは、アクセスと管理を容易にする有料サービス PikaPods でホストされています。Trilium チームとは直接関係ありません。",
|
||||||
"download_pikapod": "PikaPods にセットアップする",
|
"download_pikapod": "PikaPods にセットアップする",
|
||||||
"download_triliumcc": "または、trilium.cc を参照してください"
|
"download_triliumcc": "または、trilium.cc を参照してください"
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"get-started": "はじめる",
|
||||||
|
"documentation": "ドキュメント",
|
||||||
|
"support-us": "サポート"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
6
apps/website/src/translations/ko/translation.json
Normal file
6
apps/website/src/translations/ko/translation.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"hero_section": {
|
||||||
|
"github": "깃허브",
|
||||||
|
"dockerhub": "도커 허브"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -95,8 +95,7 @@
|
|||||||
"get_started": "Start"
|
"get_started": "Start"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"link_learn_more": "Dowiedz się więcej....",
|
"link_learn_more": "Dowiedz się więcej...."
|
||||||
"list_with_screenshot_alt": "Zrzut ekranu wybranej funkcji"
|
|
||||||
},
|
},
|
||||||
"download_now": {
|
"download_now": {
|
||||||
"text": "Pobierz teraz ",
|
"text": "Pobierz teraz ",
|
||||||
@ -95,8 +95,7 @@
|
|||||||
"get_started": "Începe"
|
"get_started": "Începe"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"link_learn_more": "Mai multe detalii...",
|
"link_learn_more": "Mai multe detalii..."
|
||||||
"list_with_screenshot_alt": "Captură de ecran a funcției selectate"
|
|
||||||
},
|
},
|
||||||
"download_now": {
|
"download_now": {
|
||||||
"text": "Descărcați acum ",
|
"text": "Descărcați acum ",
|
||||||
@ -106,6 +105,11 @@
|
|||||||
"linux_small": "pentru Linux",
|
"linux_small": "pentru Linux",
|
||||||
"more_platforms": "Mai multe platforme și instalarea server-ului"
|
"more_platforms": "Mai multe platforme și instalarea server-ului"
|
||||||
},
|
},
|
||||||
|
"header": {
|
||||||
|
"get-started": "Primii pași",
|
||||||
|
"documentation": "Documentație",
|
||||||
|
"support-us": "Sprijină-ne"
|
||||||
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"copyright_and_the": " și ",
|
"copyright_and_the": " și ",
|
||||||
"copyright_community": "comunitatea"
|
"copyright_community": "comunitatea"
|
||||||
@ -157,7 +161,7 @@
|
|||||||
"download_helper_desktop_macos": {
|
"download_helper_desktop_macos": {
|
||||||
"title_x64": "macOS pentru Intel",
|
"title_x64": "macOS pentru Intel",
|
||||||
"title_arm64": "macOS pentru Apple Silicon",
|
"title_arm64": "macOS pentru Apple Silicon",
|
||||||
"description_x64": "Pentru Mac-uri bazate pe Intel ce rulează macOS Big Sur sau mai nou.",
|
"description_x64": "Pentru Mac-uri bazate pe Intel ce rulează macOS Monterey sau mai nou.",
|
||||||
"description_arm64": "Pentru Mac-uri bazate pe Apple Silicon, precum cele cu chip-uri M1, M2.",
|
"description_arm64": "Pentru Mac-uri bazate pe Apple Silicon, precum cele cu chip-uri M1, M2.",
|
||||||
"quick_start": "Instalați prin Homebrew:",
|
"quick_start": "Instalați prin Homebrew:",
|
||||||
"download_dmg": "Descarcă instalatorul (.dmg)",
|
"download_dmg": "Descarcă instalatorul (.dmg)",
|
||||||
1
apps/website/src/translations/sr/translation.json
Normal file
1
apps/website/src/translations/sr/translation.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
1
apps/website/src/translations/tr/translation.json
Normal file
1
apps/website/src/translations/tr/translation.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -51,7 +51,8 @@
|
|||||||
"mermaid_description": "使用 Mermaid 語法繪製流程圖、類別圖與序列圖、甘特圖等多種圖表。",
|
"mermaid_description": "使用 Mermaid 語法繪製流程圖、類別圖與序列圖、甘特圖等多種圖表。",
|
||||||
"mindmap_title": "心智圖",
|
"mindmap_title": "心智圖",
|
||||||
"mindmap_description": "以視覺方式整理思緒,或進行腦力激盪。",
|
"mindmap_description": "以視覺方式整理思緒,或進行腦力激盪。",
|
||||||
"others_list": "及其他項目:<0>筆記地圖</0>、<1>關聯地圖</1>、<2>儲存搜尋</2>、<3>渲染筆記</3>,以及<4>網頁檢視</4>。"
|
"others_list": "及其他項目:<0>筆記地圖</0>、<1>關聯地圖</1>、<2>儲存搜尋</2>、<3>渲染筆記</3>,以及<4>網頁檢視</4>。",
|
||||||
|
"title": "多種方式呈現您的資訊"
|
||||||
},
|
},
|
||||||
"extensibility_benefits": {
|
"extensibility_benefits": {
|
||||||
"title": "分享及擴展性",
|
"title": "分享及擴展性",
|
||||||
@ -72,7 +73,10 @@
|
|||||||
"board_title": "看板",
|
"board_title": "看板",
|
||||||
"board_description": "將您的任務或專案狀態整理成看板,輕鬆建立新項目與欄位,並透過在看板上拖曳即可簡單變更狀態。",
|
"board_description": "將您的任務或專案狀態整理成看板,輕鬆建立新項目與欄位,並透過在看板上拖曳即可簡單變更狀態。",
|
||||||
"geomap_title": "地理地圖",
|
"geomap_title": "地理地圖",
|
||||||
"geomap_description": "使用可自訂的標記,直接在地圖上規劃您的假期行程或標記感興趣的地點。顯示已記錄的GPX軌跡,以便追蹤行程路線。"
|
"geomap_description": "使用可自訂的標記,直接在地圖上規劃您的假期行程或標記感興趣的地點。顯示已記錄的GPX軌跡,以便追蹤行程路線。",
|
||||||
|
"title": "集合",
|
||||||
|
"presentation_title": "簡報",
|
||||||
|
"presentation_description": "將資訊整理成投影片,並以全螢幕模式及流暢的轉場效果呈現。投影片亦可匯出為 PDF 格式,方便分享。"
|
||||||
},
|
},
|
||||||
"faq": {
|
"faq": {
|
||||||
"title": "常見問題",
|
"title": "常見問題",
|
||||||
@ -95,8 +99,7 @@
|
|||||||
"get_started": "上手指南"
|
"get_started": "上手指南"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"link_learn_more": "了解更多…",
|
"link_learn_more": "了解更多…"
|
||||||
"list_with_screenshot_alt": "已選擇功能的螢幕截圖"
|
|
||||||
},
|
},
|
||||||
"download_now": {
|
"download_now": {
|
||||||
"text": "馬上下載 ",
|
"text": "馬上下載 ",
|
||||||
@ -163,7 +166,7 @@
|
|||||||
"download_helper_desktop_macos": {
|
"download_helper_desktop_macos": {
|
||||||
"title_x64": "macOS 適用於 Intel",
|
"title_x64": "macOS 適用於 Intel",
|
||||||
"title_arm64": "macOS 適用於 Apple Silicon",
|
"title_arm64": "macOS 適用於 Apple Silicon",
|
||||||
"description_x64": "適用於搭載 Intel 處理器的 Mac,並運行 macOS Big Sur 或更新版本。",
|
"description_x64": "適用於搭載 Intel 處理器的 Mac,並運行 macOS Monterey 或更新版本。",
|
||||||
"description_arm64": "適用於搭載 Apple Silicon 的 Mac,例如配備 M1 和 M2 晶片的機型。",
|
"description_arm64": "適用於搭載 Apple Silicon 的 Mac,例如配備 M1 和 M2 晶片的機型。",
|
||||||
"quick_start": "透過 Homebrew 安裝:",
|
"quick_start": "透過 Homebrew 安裝:",
|
||||||
"download_dmg": "下載安裝程式 (.dmg)",
|
"download_dmg": "下載安裝程式 (.dmg)",
|
||||||
@ -188,5 +191,10 @@
|
|||||||
"description": "Trilium Notes 託管於 PikaPods,此為付費服務,提供便捷存取與管理功能。與 Trilium 團隊無直接關聯。",
|
"description": "Trilium Notes 託管於 PikaPods,此為付費服務,提供便捷存取與管理功能。與 Trilium 團隊無直接關聯。",
|
||||||
"download_pikapod": "在 PikaPods 上設定",
|
"download_pikapod": "在 PikaPods 上設定",
|
||||||
"download_triliumcc": "或參見 trilium.cc"
|
"download_triliumcc": "或參見 trilium.cc"
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"get-started": "上手指南",
|
||||||
|
"documentation": "文件",
|
||||||
|
"support-us": "支持我們"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9,6 +9,9 @@
|
|||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"jsxImportSource": "preact",
|
"jsxImportSource": "preact",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"types": [
|
||||||
|
"vite/client"
|
||||||
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"react": ["../../node_modules/preact/compat/"],
|
"react": ["../../node_modules/preact/compat/"],
|
||||||
"react-dom": ["../../node_modules/preact/compat/"]
|
"react-dom": ["../../node_modules/preact/compat/"]
|
||||||
|
|||||||
@ -14,4 +14,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
test: {
|
||||||
|
environment: "happy-dom"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user