Merge branch 'develop' into open_in_file_manager_of_data

This commit is contained in:
SiriusXT 2024-09-09 14:50:01 +08:00
commit 3ad2d1a309
61 changed files with 2327 additions and 2204 deletions

View File

@ -1,14 +1,4 @@
on:
push:
branches:
- "develop"
- "feature/update**"
- "feature/server_esm**"
paths-ignore:
- "docs/**"
- "bin/**"
tags:
- "v*"
workflow_dispatch:
env:

View File

@ -16,7 +16,7 @@ env:
DOCKERHUB_REGISTRY: docker.io
IMAGE_NAME: ${{ github.repository }}
TEST_TAG: triliumnext/notes:test
PLATFORMS: linux/arm64,linux/arm/v7
PLATFORMS: linux/amd64,linux/arm64,linux/arm/v7
jobs:
test_docker:

View File

@ -2,14 +2,11 @@ name: Main
on:
push:
branches:
- "develop"
- "feature/update**"
- "feature/server_esm**"
paths-ignore:
- "docs/**"
- ".github/workflows/main-docker.yml"
tags:
- "v*"
workflow_dispatch:
concurrency:

95
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,95 @@
name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
permissions:
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
make-electron:
name: Make Electron
strategy:
fail-fast: false
matrix:
arch: [x64, arm64]
os:
- name: macos
image: macos-latest
extension: dmg
- name: linux
image: ubuntu-latest
extension: deb
- name: windows
image: windows-latest
extension: exe
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
node-version: 20
- name: Set up Python for appdmg to be installed
if: ${{ matrix.os.name == 'macos' }}
run: brew install python-setuptools
- name: Install dependencies
run: npm ci
- name: Update build info
run: npm run update-build-info
- name: Run electron-forge
run: npm run make-electron -- --arch=${{ matrix.arch }}
- name: Prepare artifacts (Unix)
if: runner.os != 'windows'
run: |
mkdir -p upload
file=$(find out/make -name '*.zip' -print -quit)
cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.zip"
file=$(find out/make -name '*.${{ matrix.os.extension }}' -print -quit)
cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.${{ matrix.os.extension }}"
- name: Prepare artifacts (Windows)
if: runner.os == 'windows'
run: |
mkdir upload
$file = Get-ChildItem -Path out/make -Filter '*.zip' -Recurse | Select-Object -First 1
Copy-Item -Path $file.FullName -Destination "upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.zip"
$file = Get-ChildItem -Path out/make -Filter '*.${{ matrix.os.extension }}' -Recurse | Select-Object -First 1
Copy-Item -Path $file.FullName -Destination "upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.${{ matrix.os.extension }}"
- name: Publish release
uses: softprops/action-gh-release@v2
with:
draft: true
fail_on_unmatched_files: true
files: upload/*.*
build_linux_server-x64:
name: Build Linux Server x86_64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run Linux server build (x86_64)
run: |
npm run update-build-info
./bin/build-server.sh
- name: Prepare artifacts
if: runner.os != 'windows'
run: |
mkdir -p upload
file=$(find dist -name '*.tar.xz' -print -quit)
cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-server-linux-x64.tar.xz"
- name: Publish release
uses: softprops/action-gh-release@v2
with:
draft: true
fail_on_unmatched_files: true
files: upload/*.*

View File

@ -3,6 +3,7 @@
languageIds:
- javascript
- typescript
- html
# An array of RegExes to find the key usage. **The key should be captured in the first match group**.
# You should unescape RegEx strings in order to fit in the YAML file
@ -25,6 +26,7 @@ scopeRangeRegex: "useTranslation\\(\\s*\\[?\\s*['\"`](.*?)['\"`]"
refactorTemplates:
- t("$1")
- ${t("$1")}
- <%= t("$1") %>
# If set to true, only enables this custom framework (will disable all built-in frameworks)

View File

@ -6,7 +6,8 @@
"i18n-ally.sourceLanguage": "en",
"i18n-ally.keystyle": "nested",
"i18n-ally.localesPaths": [
"./src/public/translations"
"./src/public/translations",
"./translations"
],
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
@ -14,4 +15,7 @@
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
}

View File

@ -1,6 +1,6 @@
# TriliumNext Notes
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md)
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md) | [Spanish](https://github.com/TriliumNext/Notes/blob/master/README.es.md)
TriliumNext Notes 是一个层次化的笔记应用程序,专注于建立大型个人知识库。请参阅[屏幕截图](https://triliumnext.github.io/Docs/Wiki/screenshot-tour)以快速了解:
@ -76,7 +76,7 @@ Trilium 也提供 Flatpak
或者克隆本仓库到本地,并运行
```
```shell
npm install
npm run start-server
```

106
README.es.md Normal file
View File

@ -0,0 +1,106 @@
# TriliumNext Notes
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md) | [Spanish](https://github.com/TriliumNext/Notes/blob/master/README.es.md)
TriliumNext Notes es una aplicación de toma de notas jerárquicas multi-plataforma y de código libre con un enfoque en la construcción de grandes bases de conocimiento personal.
Vea estas [capturas de pantalla](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) para un vistazo rápido:
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="https://github.com/TriliumNext/Docs/blob/main/Wiki/images/screenshot.png?raw=true" alt="Trilium Screenshot" width="1000"></a>
## ⚠️ ¿Por qué usar TriliumNext?
[El proyecto Trilium original está en modo de mantenimiento](https://github.com/zadam/trilium/issues/4620)
### ¿Cómo migrar desde Trilium?
No hay pasos de migración especiales para migrar de una instancia de zadam/Trilium a una instancia de TriliumNext/Notes. Simplemente actualice su instancia de Trilium a la última versión e [instale TriliumNext/Notes como de costumbre](#-Instalación)
## 💬 Discuta con nosotros
Siéntase libre de unirse a nuestras conversaciones oficiales. ¡Nos encantaría escuchar de las características, sugerencias o problemas que pueda tener!
- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (Para discusiones síncronas)
- La sala `General` es replicada a [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
- [Discusiones de GitHub](https://github.com/TriliumNext/Notes/discussions) (Para discusiones asíncronas)
- [Wiki](https://triliumnext.github.io/Docs/) (Para preguntas frecuentes y guías de usuario)
## 🎁 Características
- Las notas pueden ser acomodadas en un árbol de profundidad arbitraria. Una sola nota puede ser colocada en múltiples lugares del árbol (vea [clonar](https://triliumnext.github.io/Docs/Wiki/cloning-notes)
- Edición de notas WYSIWYG enriquecida que incluye, por ejemplo, tablas, imágenes y [matemáticas](https://triliumnext.github.io/Docs/Wiki/text-notes) con [autoformato](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat) markdown
- Soporte para editar [notas con código fuente](https://triliumnext.github.io/Docs/Wiki/code-notes), incluyendo resaltado de sintaxis
- Rápida y sencilla [navegación entre notas](https://triliumnext.github.io/Docs/Wiki/note-navigation), búsqueda de texto completo y [elevación de notas](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
- [Versionado de notas](https://triliumnext.github.io/Docs/Wiki/note-revisions) sutil
- Los [atributos](https://triliumnext.github.io/Docs/Wiki/attributes) de las notas pueden utilizarse para organización, realizar consultas y [scripts](https://triliumnext.github.io/Docs/Wiki/scripts) avanzados
- [Sincronización](https://triliumnext.github.io/Docs/Wiki/synchronization) con servidor de sincronización propio
- existe un [servicio de terceros para alojar el servidor de sincronización](https://trilium.cc/paid-hosting)
- [Compartir](https://triliumnext.github.io/Docs/Wiki/sharing) (publicar) notas al Internet público
- Fuerte [encriptación de notas](https://triliumnext.github.io/Docs/Wiki/protected-notes) con granularidad para cada nota
- Esbozo de diagramas con Excalidraw incorporado (tipo de nota «canvas»)
- [Mapas de relaciones](<https://triliumnext.github.io/Docs/Wiki/relation-map>) y [mapas de enlaces](https://triliumnext.github.io/Docs/Wiki/link-map) para visualizar las notas y sus relaciones
- [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - vea [casos de uso avanzados](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
- [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) para automatización
- Escala bien tanto en uso como en rendimiento a partir de 100,000 notas
- [Interfaz móvil](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) optimizada para teléfonos inteligentes y tabletas
- [Tema nocturno](https://triliumnext.github.io/Docs/Wiki/themes)
- Importación y exportación de [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) y [Markdown](https://triliumnext.github.io/Docs/Wiki/markdown)
- [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) para guardar fácilmente contenido web
✨ Consulte los/las siguientes recursos/comunidades de terceros para obtener más información sobre complementos para TriliumNext:
- [awesome-trilium](https://github.com/Nriver/awesome-trilium) para temas, scripts, plugins y más de terceros.
- [TriliumRocks!](https://trilium.rocks/) para tutoriales, guías y mucho más.
## 🏗 Instalación
### Escritorio
Para usar TriliumNext en su máquina de escritorio (Linux, MacOS y Windows) tiene algunas opciones:
- Descargue la versión binaria para su plataforma desde la [página de lanzamientos](https://github.com/TriliumNext/Notes/releases/latest), descomprima el paquete y ejecute el ejecutable `trilium`.
- Acceda a TriliumNext a través de la interfaz web de una instalación de servidor (ver más abajo)
- Actualmente solo las últimas versiones de Chrome y Firefox son compatibles (y están probadas).
- (Próximamente) TriliumNext también se proporcionará como un Flatpak
### Móvil
Para usar TriliumNext en un dispositivo móvil:
- Utilice un navegador web móvil para acceder a la interfaz móvil de una instalación de servidor (ver más abajo)
- El uso de una aplicación móvil aún no está soportado ([vea aquí](https://github.com/TriliumNext/Notes/issues/72)) para seguir las mejoras móviles.
### Servidor
Para instalar TriliumNext en su servidor (incluyendo vía Docker desde [Dockerhub](https://hub.docker.com/r/triliumnext/notes)) siga la [documentación de instalación de servidor](https://triliumnext.github.io/Docs/Wiki/server-installation).
## 📝 Documentación
[Vea la Wiki para la lista completa de páginas de documentación.](https://triliumnext.github.io/Docs)
También puede leer [Patrones para una base de conocimiento personal](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge) para obtener un poco de inspiración de como podría usar TriliumNext.
## 💻 Contribuir
Clone localmente y ejecute
```shell
npm install
npm run start-server
```
## 👏 Reconocimientos
- [CKEditor 5](https://github.com/ckeditor/ckeditor5) - el mejor editor WYSIWYG en el mercado, equipo muy interactivo y atento
- [FancyTree](https://github.com/mar10/fancytree) - biblioteca de árbol muy rica en funciones sin competencia real. TriliumNext Notes no sería lo mismo sin esta.
- [CodeMirror](https://github.com/codemirror/CodeMirror) - editor de código con soporte para una gran cantidad de lenguajes
- [jsPlumb](https://github.com/jsplumb/jsplumb) - biblioteca de conectividad visual sin competencia. Usado en [mapas de relación](https://triliumnext.github.io/Docs/Wiki/Relation-map) y [mapas de enlace](https://triliumnext.github.io/Docs/Wiki/Link-map)
## 🤝 Soporte
Puede apoyar al desarrollador original de Trilium usando GitHub Sponsors, [PayPal](https://paypal.me/za4am) o Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
Apoyo para la organización TriliumNext será posible en un futuro próximo.
## 🔑 Licencia
Este programa es software libre: puede redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General de Affero GNU publicada por la Free Software Foundation, ya sea la versión 3 de la Licencia, o (a su elección) cualquier versión posterior.

View File

@ -1,6 +1,6 @@
# TriliumNext Notes
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md)
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md) | [Spanish](https://github.com/TriliumNext/Notes/blob/master/README.es.md)
TriliumNext Notes è un'applicazione per appunti ad organizzazione gerarchica, studiata per la costruzione di archivi di conoscenza personali di grandi dimensioni.
@ -70,7 +70,8 @@ Puoi anche leggere ["Patterns of personal knowledge base"](https://triliumnext.g
## 💻 Contribuire
Clona localmente ed esegui
```
```shell
npm install
npm run start-server
```

View File

@ -1,6 +1,6 @@
# TriliumNext Notes
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md)
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md) | [Spanish](https://github.com/TriliumNext/Notes/blob/master/README.es.md)
Trilium Notes は、大規模な個人知識ベースの構築に焦点を当てた、階層型ノートアプリケーションです。概要は[スクリーンショット](https://triliumnext.github.io/Docs/Wiki/screenshot-tour)をご覧ください:
@ -51,7 +51,8 @@ Trilium は Flatpak としても提供されます:
## 💻 コントリビュート
または、ローカルにクローンして実行
```
```shell
npm install
npm run start-server
```

View File

@ -1,6 +1,6 @@
# TriliumNext Notes
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md)
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md) | [Spanish](https://github.com/TriliumNext/Notes/blob/master/README.es.md)
TriliumNext Notes is an open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.
@ -27,7 +27,7 @@ Feel free to join our official conversations. We would love to hear what feature
## 🎁 Features
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes)
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
* Rich WYSIWYG note editing including e.g. tables, images and [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
* Support for editing [notes with source code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax highlighting
* Fast and easy [navigation between notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text search and [note hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
@ -83,7 +83,8 @@ You can also read [Patterns of personal knowledge base](https://triliumnext.gith
## 💻 Contribute
Clone locally and run
```
```shell
npm install
npm run start-server
```

View File

@ -1,6 +1,6 @@
# TriliumNext Notes
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md)
[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md) | [Spanish](https://github.com/TriliumNext/Notes/blob/master/README.es.md)
Trilium Notes это приложение для заметок с иерархической структурой, ориентированное на создание больших персональных баз знаний. Для быстрого ознакомления посмотрите [скриншот-тур](https://triliumnext.github.io/Docs/Wiki/screenshot-tour):
@ -41,7 +41,8 @@ Trilium предоставляется в виде десктопного при
## 💻 Участвуйте в разработке
Или склонируйте на своё устройство и запустите
```
```shell
npm install
npm run start-server
```

View File

@ -22,7 +22,7 @@ rm -r $PKG_DIR/node/lib/node_modules/npm
rm -r $PKG_DIR/node/include/node
rm -r $PKG_DIR/node_modules/electron*
rm -r $PKG_DIR/electron.js
rm -r $PKG_DIR/electron*.js
printf "#!/bin/sh\n./node/bin/node src/www" > $PKG_DIR/trilium.sh
chmod 755 $PKG_DIR/trilium.sh

View File

@ -37,11 +37,11 @@ for f in 'package.json' 'package-lock.json' 'README.md' 'LICENSE' 'config-sample
done
# Patch package.json main
sed -i 's/.\/dist\/electron.js/electron.js/g' "$DIR/package.json"
sed -i 's/.\/dist\/electron-main.js/electron-main.js/g' "$DIR/package.json"
script_dir=$(realpath $(dirname $0))
cp -R "$script_dir/../build/src" "$DIR"
cp "$script_dir/../build/electron.js" "$DIR"
cp "$script_dir/../build/electron-main.js" "$DIR"
# run in subshell (so we return to original dir)
(cd $DIR && npm install --omit=dev)

View File

@ -47,35 +47,3 @@ echo "Tagging commit with $TAG"
git tag $TAG
git push origin $TAG
bin/build.sh
LINUX_X64_BUILD=trilium-linux-x64-$VERSION.tar.xz
DEBIAN_X64_BUILD=trilium_${VERSION}_amd64.deb
WINDOWS_X64_BUILD=trilium-windows-x64-$VERSION.zip
MAC_X64_BUILD=trilium-mac-x64-$VERSION.zip
MAC_ARM64_BUILD=trilium-mac-arm64-$VERSION.zip
SERVER_BUILD=trilium-linux-x64-server-$VERSION.tar.xz
echo "Creating release in GitHub"
EXTRA=
if [[ $TAG == *"beta"* ]]; then
EXTRA=--prerelease
fi
if [ ! -z "$GITHUB_CLI_AUTH_TOKEN" ]; then
echo "$GITHUB_CLI_AUTH_TOKEN" | gh auth login --with-token
fi
gh release create -d "$TAG" \
--title "$TAG release" \
--notes "" \
$EXTRA \
"dist/$DEBIAN_X64_BUILD" \
"dist/$LINUX_X64_BUILD" \
"dist/$WINDOWS_X64_BUILD" \
"dist/$MAC_X64_BUILD" \
"dist/$MAC_ARM64_BUILD" \
"dist/$SERVER_BUILD"

Binary file not shown.

4
electron-main.ts Normal file
View File

@ -0,0 +1,4 @@
import { initializeTranslations } from "./src/services/i18n.js";
await initializeTranslations();
await import("./electron.js")

View File

@ -70,4 +70,4 @@ electron.app.on("will-quit", () => {
// this is to disable electron warning spam in the dev console (local development only)
process.env["ELECTRON_DISABLE_SECURITY_WARNINGS"] = "true";
await import('./src/www.js');
await import('./src/main.js');

View File

@ -3,7 +3,10 @@
"ignore": [".git", "node_modules/**/node_modules", "src/public/"],
"verbose": false,
"exec": "tsx",
"watch": ["src/"],
"watch": [
"src/",
"translations/"
],
"signal": "SIGTERM",
"env": {
"NODE_ENV": "development"

2254
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,9 @@
"name": "trilium",
"productName": "TriliumNext Notes",
"description": "Build your personal knowledge base with TriliumNext Notes",
"version": "0.90.4",
"version": "0.90.6-beta",
"license": "AGPL-3.0-only",
"main": "./dist/electron.js",
"main": "./dist/electron-main.js",
"author": {
"name": "TriliumNext Notes Team",
"email": "contact@eliandoran.me",
@ -12,7 +12,7 @@
},
"copyright": "",
"bin": {
"trilium": "src/www.js"
"trilium": "src/main.js"
},
"repository": {
"type": "git",
@ -20,12 +20,12 @@
},
"type": "module",
"scripts": {
"start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
"start-server-safe": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
"start-server-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/www.ts",
"start-test-server": "npm run switch-server; rimraf ./data-test; cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data-test TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev TRILIUM_PORT=9999 ts-node src/www.ts",
"start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/main.ts",
"start-server-safe": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/main.ts",
"start-server-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/main.ts",
"start-test-server": "npm run switch-server; rimraf ./data-test; cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data-test TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev TRILIUM_PORT=9999 ts-node src/main.ts",
"qstart-server": "npm run switch-server && npm run start-server",
"start-electron": "npm run prepare-dist && cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron ./dist/electron.js --inspect=5858 .",
"start-electron": "npm run prepare-dist && cross-env TRILIUM_SAFE_MODE=1 TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron ./dist/electron-main.js --inspect=5858 .",
"start-electron-no-dir": "cross-env TRILIUM_SAFE_MODE=1 TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .",
"qstart-electron": "npm run switch-electron && npm run start-electron",
"switch-server": "rimraf ./node_modules/better-sqlite3 && npm install",
@ -43,9 +43,9 @@
"prepare-dist": "rimraf ./dist && tsc && tsx ./bin/copy-dist.ts",
"update-build-info": "tsx bin/update-build-info.ts",
"errors": "tsc --watch --noEmit",
"integration-edit-db": "cross-env TRILIUM_INTEGRATION_TEST=edit TRILIUM_PORT=8081 TRILIUM_DATA_DIR=./integration-tests/db nodemon src/www.ts",
"integration-mem-db": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_DATA_DIR=./integration-tests/db nodemon src/www.ts",
"integration-mem-db-dev": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/www.ts",
"integration-edit-db": "cross-env TRILIUM_INTEGRATION_TEST=edit TRILIUM_PORT=8081 TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
"integration-mem-db": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
"integration-mem-db-dev": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
"generate-document": "cross-env nodemon src/tools/generate_document.ts 1000"
},
"dependencies": {
@ -87,8 +87,9 @@
"html2plaintext": "2.1.4",
"http-proxy-agent": "7.0.2",
"https-proxy-agent": "^7.0.5",
"i18next": "^23.12.2",
"i18next-http-backend": "^2.5.2",
"i18next": "^23.14.0",
"i18next-fs-backend": "^2.3.2",
"i18next-http-backend": "^2.6.1",
"image-type": "4.1.0",
"ini": "^4.1.3",
"is-animated": "2.0.2",
@ -138,12 +139,12 @@
"yauzl": "^3.1.3"
},
"devDependencies": {
"@electron-forge/cli": "^6.4.2",
"@electron-forge/cli": "^7.4.0",
"@electron-forge/maker-deb": "^7.4.0",
"@electron-forge/maker-dmg": "^7.4.0",
"@electron-forge/maker-squirrel": "^6.4.2",
"@electron-forge/maker-squirrel": "^7.4.0",
"@electron-forge/maker-zip": "^7.4.0",
"@electron-forge/plugin-auto-unpack-natives": "^6.4.2",
"@electron-forge/plugin-auto-unpack-natives": "^7.4.0",
"@playwright/test": "^1.46.0",
"@types/archiver": "^6.0.2",
"@types/better-sqlite3": "^7.6.9",
@ -161,10 +162,10 @@
"@types/jasmine": "^5.1.4",
"@types/jsdom": "^21.1.6",
"@types/mime-types": "^2.1.4",
"@types/multer": "^1.4.11",
"@types/node": "^22.1.0",
"@types/multer": "^1.4.12",
"@types/node": "^22.5.2",
"@types/safe-compare": "^1.1.2",
"@types/sanitize-html": "^2.11.0",
"@types/sanitize-html": "^2.13.0",
"@types/sax": "^1.2.7",
"@types/semver": "^7.5.8",
"@types/serve-favicon": "^2.5.7",
@ -172,8 +173,8 @@
"@types/source-map-support": "^0.5.10",
"@types/stream-throttle": "^0.1.4",
"@types/tmp": "^0.2.6",
"@types/turndown": "^5.0.4",
"@types/ws": "^8.5.10",
"@types/turndown": "^5.0.5",
"@types/ws": "^8.5.12",
"@types/xml2js": "^0.4.14",
"cross-env": "7.0.3",
"electron": "^31.2.1",
@ -188,9 +189,9 @@
"rcedit": "4.0.1",
"rimraf": "^6.0.1",
"ts-node": "^10.9.2",
"tslib": "^2.6.2",
"tsx": "^4.16.2",
"typescript": "^5.3.3",
"tslib": "^2.7.0",
"tsx": "^4.19.0",
"typescript": "^5.5.4",
"webpack": "^5.93.0",
"webpack-cli": "5.1.4"
}

View File

@ -14,6 +14,7 @@ import custom from "./routes/custom.js";
import error_handlers from "./routes/error_handlers.js";
import { startScheduledCleanup } from "./services/erase.js";
import sql_init from "./services/sql_init.js";
import { t } from "i18next";
await import('./services/handlers.js');
await import('./becca/becca_loader.js');
@ -29,6 +30,11 @@ sql_init.initializeDb();
app.set('views', path.join(scriptDir, 'views'));
app.set('view engine', 'ejs');
app.use((req, res, next) => {
res.locals.t = t;
return next();
});
if (!utils.isElectron()) {
app.use(compression()); // HTTP compression
}

View File

@ -91,7 +91,7 @@ export interface BranchRow {
* end user. Those types should be used only for checking against, they are
* not for direct use.
*/
export const ALLOWED_NOTE_TYPES = [ "file", "image", "search", "noteMap", "launcher", "doc", "contentWidget", "text", "relationMap", "render", "canvas", "mermaid", "book", "webView", "code" ] as const;
export const ALLOWED_NOTE_TYPES = [ "file", "image", "search", "noteMap", "launcher", "doc", "contentWidget", "text", "relationMap", "render", "canvas", "mermaid", "book", "webView", "code", "mindMap" ] as const;
export type NoteType = typeof ALLOWED_NOTE_TYPES[number];
export interface NoteRow {

13
src/main.ts Normal file
View File

@ -0,0 +1,13 @@
/*
* Make sure not to import any modules that depend on localized messages via i18next here, as the initializations
* are loaded later and will result in an empty string.
*/
import { initializeTranslations } from "./services/i18n.js";
async function startApplication() {
await import("./www.js");
}
await initializeTranslations();
await startApplication();

View File

@ -8,6 +8,7 @@ import noteTypesService from "../services/note_types.js";
import server from "../services/server.js";
import toastService from "../services/toast.js";
import dialogService from "../services/dialog.js";
import { t } from "../services/i18n.js";
export default class TreeContextMenu {
/**
@ -48,55 +49,55 @@ export default class TreeContextMenu {
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
return [
{ title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes },
{ title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "bx bx-plus",
{ title: `${t("tree-context-menu.open-in-a-new-tab")} <kbd>Ctrl+Click</kbd>`, command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.insert-note-after")} <kbd data-command="createNoteAfter"></kbd>`, command: "insertNoteAfter", uiIcon: "bx bx-plus",
items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
enabled: insertNoteAfterEnabled && noSelectedNotes && notOptions },
{ title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "bx bx-plus",
{ title: `${t("tree-context-menu.insert-child-note")} <kbd data-command="createNoteInto"></kbd>`, command: "insertChildNote", uiIcon: "bx bx-plus",
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes && notOptions },
{ title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash",
{ title: `${t("tree-context-menu.delete")} <kbd data-command="deleteNotes"></kbd>`, command: "deleteNotes", uiIcon: "bx bx-trash",
enabled: isNotRoot && !isHoisted && parentNotSearch && notOptions },
{ title: "----" },
{ title: 'Search in subtree <kbd data-command="searchInSubtree"></kbd>', command: "searchInSubtree", uiIcon: "bx bx-search",
{ title: `${t("tree-context-menu.search-in-subtree")} <kbd data-command="searchInSubtree"></kbd>`, command: "searchInSubtree", uiIcon: "bx bx-search",
enabled: notSearch && noSelectedNotes },
isHoisted ? null : { title: 'Hoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
!isHoisted || !isNotRoot ? null : { title: 'Unhoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ title: 'Edit branch prefix <kbd data-command="editBranchPrefix"></kbd>', command: "editBranchPrefix", uiIcon: "bx bx-empty",
{ title: `${t("tree-context-menu.edit-branch-prefix")} <kbd data-command="editBranchPrefix"></kbd>`, command: "editBranchPrefix", uiIcon: "bx bx-empty",
enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptions },
{ title: "Advanced", uiIcon: "bx bx-empty", enabled: true, items: [
{ title: 'Expand subtree <kbd data-command="expandSubtree"></kbd>', command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: 'Collapse subtree <kbd data-command="collapseSubtree"></kbd>', command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ title: 'Sort by ... <kbd data-command="sortChildNotes"></kbd>', command: "sortChildNotes", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
{ title: 'Recent changes in subtree', command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptions },
{ title: 'Convert to attachment', command: "convertNoteToAttachment", uiIcon: "bx bx-empty", enabled: isNotRoot && !isHoisted && notOptions },
{ title: 'Copy note path to clipboard', command: "copyNotePathToClipboard", uiIcon: "bx bx-empty", enabled: true }
{ title: t("tree-context-menu.advanced"), uiIcon: "bx bx-empty", enabled: true, items: [
{ title: `${t("tree-context-menu.expand-subtree")} <kbd data-command="expandSubtree"></kbd>`, command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.collapse-subtree")} <kbd data-command="collapseSubtree"></kbd>`, command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.sort-by")} <kbd data-command="sortChildNotes"></kbd>`, command: "sortChildNotes", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
{ title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptions },
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-empty", enabled: isNotRoot && !isHoisted && notOptions },
{ title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-empty", enabled: true }
] },
{ title: "----" },
{ title: "Protect subtree", command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
{ title: "Unprotect subtree", command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes },
{ title: t("tree-context-menu.protect-subtree"), command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
{ title: t("tree-context-menu.unprotect-subtree"), command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes },
{ title: "----" },
{ title: 'Copy / clone <kbd data-command="copyNotesToClipboard"></kbd>', command: "copyNotesToClipboard", uiIcon: "bx bx-copy",
{ title: `${t("tree-context-menu.copy-clone")} <kbd data-command="copyNotesToClipboard"></kbd>`, command: "copyNotesToClipboard", uiIcon: "bx bx-copy",
enabled: isNotRoot && !isHoisted },
{ title: 'Clone to ... <kbd data-command="cloneNotesTo"></kbd>', command: "cloneNotesTo", uiIcon: "bx bx-empty",
{ title: `${t("tree-context-menu.clone-to")} <kbd data-command="cloneNotesTo"></kbd>`, command: "cloneNotesTo", uiIcon: "bx bx-empty",
enabled: isNotRoot && !isHoisted },
{ title: 'Cut <kbd data-command="cutNotesToClipboard"></kbd>', command: "cutNotesToClipboard", uiIcon: "bx bx-cut",
{ title: `${t("tree-context-menu.cut")} <kbd data-command="cutNotesToClipboard"></kbd>`, command: "cutNotesToClipboard", uiIcon: "bx bx-cut",
enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: 'Move to ... <kbd data-command="moveNotesTo"></kbd>', command: "moveNotesTo", uiIcon: "bx bx-empty",
{ title: `${t("tree-context-menu.move-to")} <kbd data-command="moveNotesTo"></kbd>`, command: "moveNotesTo", uiIcon: "bx bx-empty",
enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: 'Paste into <kbd data-command="pasteNotesFromClipboard"></kbd>', command: "pasteNotesFromClipboard", uiIcon: "bx bx-paste",
{ title: `${t("tree-context-menu.paste-into")} <kbd data-command="pasteNotesFromClipboard"></kbd>`, command: "pasteNotesFromClipboard", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes },
{ title: 'Paste after', command: "pasteNotesAfterFromClipboard", uiIcon: "bx bx-paste",
{ title: t("tree-context-menu.paste-after"), command: "pasteNotesAfterFromClipboard", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && isNotRoot && !isHoisted && parentNotSearch && noSelectedNotes },
{ title: `Duplicate subtree <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-empty",
{ title: `${t("tree-context-menu.duplicate-subtree")} <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-empty",
enabled: parentNotSearch && isNotRoot && !isHoisted && notOptions },
{ title: "----" },
{ title: "Export", command: "exportNote", uiIcon: "bx bx-empty",
{ title: t("tree-context-menu.export"), command: "exportNote", uiIcon: "bx bx-empty",
enabled: notSearch && noSelectedNotes && notOptions },
{ title: "Import into note", command: "importIntoNote", uiIcon: "bx bx-empty",
{ title: t("tree-context-menu.import-into-note"), command: "importIntoNote", uiIcon: "bx bx-empty",
enabled: notSearch && noSelectedNotes && notOptions },
{ title: "Apply bulk actions", command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus",
{ title: t("tree-context-menu.apply-bulk-actions"), command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus",
enabled: true }
].filter(row => row !== null);
}

View File

@ -1,19 +1,20 @@
import server from "./server.js";
import froca from "./froca.js";
import { t } from "./i18n.js";
async function getNoteTypeItems(command) {
const items = [
{ title: "Text", command: command, type: "text", uiIcon: "bx bx-note" },
{ title: "Code", command: command, type: "code", uiIcon: "bx bx-code" },
{ title: "Saved Search", command: command, type: "search", uiIcon: "bx bx-file-find" },
{ title: "Relation Map", command: command, type: "relationMap", uiIcon: "bx bx-map-alt" },
{ title: "Note Map", command: command, type: "noteMap", uiIcon: "bx bx-map-alt" },
{ title: "Render Note", command: command, type: "render", uiIcon: "bx bx-extension" },
{ title: "Book", command: command, type: "book", uiIcon: "bx bx-book" },
{ title: "Mermaid Diagram", command: command, type: "mermaid", uiIcon: "bx bx-selection" },
{ title: "Canvas", command: command, type: "canvas", uiIcon: "bx bx-pen" },
{ title: "Web View", command: command, type: "webView", uiIcon: "bx bx-globe-alt" },
{ title: "Mind Map", command, type: "mindMap", uiIcon: "bx bx-sitemap" }
{ title: t("note_types.text"), command: command, type: "text", uiIcon: "bx bx-note" },
{ title: t("note_types.code"), command: command, type: "code", uiIcon: "bx bx-code" },
{ title: t("note_types.saved-search"), command: command, type: "search", uiIcon: "bx bx-file-find" },
{ title: t("note_types.relation-map"), command: command, type: "relationMap", uiIcon: "bx bx-map-alt" },
{ title: t("note_types.note-map"), command: command, type: "noteMap", uiIcon: "bx bx-map-alt" },
{ title: t("note_types.render-note"), command: command, type: "render", uiIcon: "bx bx-extension" },
{ title: t("note_types.book"), command: command, type: "book", uiIcon: "bx bx-book" },
{ title: t("note_types.mermaid-diagram"), command: command, type: "mermaid", uiIcon: "bx bx-selection" },
{ title: t("note_types.canvas"), command: command, type: "canvas", uiIcon: "bx bx-pen" },
{ title: t("note_types.web-view"), command: command, type: "webView", uiIcon: "bx bx-globe-alt" },
{ title: t("note_types.mind-map"), command, type: "mindMap", uiIcon: "bx bx-sitemap" }
];
const templateNoteIds = await server.get("search-templates");

View File

@ -128,7 +128,10 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
else {
toastService.showError(t("calendar.cannot_find_day_note"));
}
});
});
// Prevent dismissing the calendar popup by clicking on an empty space inside it.
this.$dropdownContent.on("click", (e) => e.stopPropagation());
}
manageFirstDayOfWeek() {

View File

@ -17,7 +17,7 @@ const TPL = `
}
.note-actions .dropdown-menu {
width: 15em;
min-width: 15em;
}
.note-actions .dropdown-item[disabled], .note-actions .dropdown-item[disabled]:hover {

View File

@ -7,7 +7,6 @@ export default class OnClickButtonWidget extends AbstractButtonWidget {
if (this.settings.onClick) {
this.$widget.on("click", e => {
e.stopPropagation();
this.$widget.tooltip("hide");
this.settings.onClick(this, e);

View File

@ -33,7 +33,7 @@ const TPL = `
${t("note_type_chooser.modal_body")}
<div class="dropdown">
<button class="note-type-dropdown-trigger" type="button" style="display: none;" data-toggle="dropdown">${t("note_type_chooser.dropdown_trigger")}</button>
<button class="note-type-dropdown-trigger" type="button" style="display: none;" data-toggle="dropdown"></button>
<div class="note-type-dropdown dropdown-menu"></div>
</div>

View File

@ -54,7 +54,7 @@ const TPL = `
</div>
<div class="modal-body" style="display: flex; height: 80vh;">
<div class="dropdown">
<button class="revision-list-dropdown" type="button" style="display: none;" data-toggle="dropdown">${t("revisions.dropdown_trigger")}</button>
<button class="revision-list-dropdown" type="button" style="display: none;" data-toggle="dropdown"></button>
<div class="revision-list dropdown-menu" style="position: static; height: 100%; overflow: auto;"></div>
</div>
@ -274,7 +274,7 @@ export default class RevisionsDialog extends BasicWidget {
}
this.$content.html($table);
} else if (revisionItem.type === 'canvas') {
} else if ([ "canvas", "mindMap" ].includes(revisionItem.type)) {
const encodedTitle = encodeURIComponent(revisionItem.title);
this.$content.html($("<img>")

View File

@ -6,6 +6,7 @@ import appContext from "../components/app_context.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js";
import linkContextMenuService from "../menus/link_context_menu.js";
import utils from "../services/utils.js";
import { t } from "../services/i18n.js";
const esc = utils.escapeHtml;
@ -30,8 +31,8 @@ const TPL = `<div class="note-map-widget" style="position: relative;">
</style>
<div class="btn-group btn-group-sm map-type-switcher" role="group">
<button type="button" class="btn bx bx-network-chart" title="Link Map" data-type="link"></button>
<button type="button" class="btn bx bx-sitemap" title="Tree map" data-type="tree"></button>
<button type="button" class="btn bx bx-network-chart" title="${t("note-map.button-link-map")}" data-type="link"></button>
<button type="button" class="btn bx bx-sitemap" title="${t("note-map.button-tree-map")}" data-type="tree"></button>
</div>
<div class="style-resolver"></div>

View File

@ -2,25 +2,26 @@ import server from '../services/server.js';
import mimeTypesService from '../services/mime_types.js';
import NoteContextAwareWidget from "./note_context_aware_widget.js";
import dialogService from "../services/dialog.js";
import { t } from '../services/i18n.js';
const NOTE_TYPES = [
{ type: "file", title: "File", selectable: false },
{ type: "image", title: "Image", selectable: false },
{ type: "search", title: "Saved Search", selectable: false },
{ type: "noteMap", mime: '', title: "Note Map", selectable: false },
{ type: "launcher", mime: '', title: "Launcher", selectable: false },
{ type: "doc", mime: '', title: "Doc", selectable: false },
{ type: "contentWidget", mime: '', title: "Widget", selectable: false },
{ type: "file", title: t("note_types.file"), selectable: false },
{ type: "image", title: t("note_types.image"), selectable: false },
{ type: "search", title: t("note_types.saved-search"), selectable: false },
{ type: "noteMap", mime: '', title: t("note_types.note-map"), selectable: false },
{ type: "launcher", mime: '', title: t("note_types.launcher"), selectable: false },
{ type: "doc", mime: '', title: t("note_types.doc"), selectable: false },
{ type: "contentWidget", mime: '', title: t("note_types.widget"), selectable: false },
{ type: "text", mime: "text/html", title: "Text", selectable: true },
{ type: "relationMap", mime: "application/json", title: "Relation Map", selectable: true },
{ type: "mindMap", mime: "application/json", "title": "Mind Map", selectable: true },
{ type: "render", mime: '', title: "Render Note", selectable: true },
{ type: "canvas", mime: 'application/json', title: "Canvas", selectable: true },
{ type: "mermaid", mime: 'text/mermaid', title: "Mermaid Diagram", selectable: true },
{ type: "book", mime: '', title: "Book", selectable: true },
{ type: "webView", mime: '', title: "Web View", selectable: true },
{ type: "code", mime: 'text/plain', title: "Code", selectable: true }
{ type: "text", mime: "text/html", title: t("note_types.text"), selectable: true },
{ type: "relationMap", mime: "application/json", title: t("note_types.relation-map"), selectable: true },
{ type: "mindMap", mime: "application/json", "title": t("note_types.mind-map"), selectable: true },
{ type: "render", mime: '', title: t("note_types.render-note"), selectable: true },
{ type: "canvas", mime: 'application/json', title: t("note_types.canvas"), selectable: true },
{ type: "mermaid", mime: 'text/mermaid', title: t("note_types.mermaid-diagram"), selectable: true },
{ type: "book", mime: '', title: t("note_types.book"), selectable: true },
{ type: "webView", mime: '', title: t("note_types.web-view"), selectable: true },
{ type: "code", mime: 'text/plain', title: t("note_types.code"), selectable: true }
];
const NOT_SELECTABLE_NOTE_TYPES = NOTE_TYPES.filter(nt => !nt.selectable).map(nt => nt.type);

View File

@ -1,3 +1,4 @@
import { t } from "../services/i18n.js";
import protectedSessionService from "../services/protected_session.js";
import SwitchWidget from "./switch.js";
@ -5,11 +6,11 @@ export default class ProtectedNoteSwitchWidget extends SwitchWidget {
doRender() {
super.doRender();
this.$switchOnName.text("Protect the note");
this.$switchOnButton.attr("title", "Note is not protected, click to make it protected");
this.$switchOnName.text(t("protect_note.toggle-on"));
this.$switchOnButton.attr("title", t("protect_note.toggle-on-hint"));
this.$switchOffName.text("Unprotect the note");
this.$switchOffButton.attr("title", "Note is protected, click to make it unprotected");
this.$switchOffName.text(t("protect_note.toggle-off"));
this.$switchOffButton.attr("title", t("protect_note.toggle-off-hint"));
}
switchOn() {

View File

@ -1,6 +1,7 @@
import NoteContextAwareWidget from "./note_context_aware_widget.js";
import options from "../services/options.js";
import attributeService from "../services/attributes.js";
import { t } from "../services/i18n.js";
const TPL = `
<div class="shared-info-widget alert alert-warning">
@ -13,7 +14,7 @@ const TPL = `
}
</style>
<span class="shared-text"></span> <a class="shared-link external"></a>. For help visit <a href="https://triliumnext.github.io/Docs/Wiki/sharing.html">wiki</a>.
<span class="shared-text"></span> <a class="shared-link external"></a>. ${t("shared_info.help_link")}
</div>`;
export default class SharedInfoWidget extends NoteContextAwareWidget {
@ -36,7 +37,7 @@ export default class SharedInfoWidget extends NoteContextAwareWidget {
if (syncServerHost) {
link = `${syncServerHost}/share/${shareId}`;
this.$sharedText.text("This note is shared publicly on");
this.$sharedText.text(t("shared_info.shared_publicly"));
}
else {
let host = location.host;
@ -47,7 +48,7 @@ export default class SharedInfoWidget extends NoteContextAwareWidget {
}
link = `${location.protocol}//${host}${location.pathname}share/${shareId}`;
this.$sharedText.text("This note is shared locally on");
this.$sharedText.text(t("shared_info.shared_locally"));
}
this.$sharedLink.attr("href", link).text(link);

View File

@ -4,6 +4,7 @@ import server from "../services/server.js";
import utils from "../services/utils.js";
import syncService from "../services/sync.js";
import dialogService from "../services/dialog.js";
import { t } from "../services/i18n.js";
export default class SharedSwitchWidget extends SwitchWidget {
isEnabled() {
@ -15,11 +16,11 @@ export default class SharedSwitchWidget extends SwitchWidget {
doRender() {
super.doRender();
this.$switchOnName.text("Shared");
this.$switchOnButton.attr("title", "Share the note");
this.$switchOnName.text(t("shared_switch.shared"));
this.$switchOnButton.attr("title", t("shared_switch.toggle-on-title"));
this.$switchOffName.text("Shared");
this.$switchOffButton.attr("title", "Unshare the note");
this.$switchOffName.text(t("shared_switch.shared"));
this.$switchOffButton.attr("title", t("shared_switch.toggle-off-title"));
this.$helpButton.attr("data-help-page", "sharing.html").show();
this.$helpButton.on('click', e => utils.openHelp($(e.target)));
@ -39,9 +40,7 @@ export default class SharedSwitchWidget extends SwitchWidget {
}
if (this.note.getParentBranches().length === 1) {
const text = "This note exists only as a shared note, unsharing would delete it. Do you want to continue and thus delete this note?";
if (!await dialogService.confirm(text)) {
if (!await dialogService.confirm(t("shared_switch.shared-branch"))) {
return;
}
}
@ -60,7 +59,7 @@ export default class SharedSwitchWidget extends SwitchWidget {
this.$switchOff.toggle(!!isShared);
if (switchDisabled) {
this.$widget.attr("title", "Note cannot be unshared here because it is shared through inheritance from an ancestor.");
this.$widget.attr("title", t("shared_switch.inherited"));
this.$switchOff.addClass("switch-disabled");
}
else {

View File

@ -1,3 +1,4 @@
import { t } from "../services/i18n.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js";
const TPL = `
@ -90,7 +91,7 @@ const TPL = `
</span>
</div>
<button class="switch-help-button" type="button" data-help-page="" title="Open help page" style="display: none;">?</button>
<button class="switch-help-button" type="button" data-help-page="" title="${t("open-help-page")}" style="display: none;">?</button>
</div>`;
export default class SwitchWidget extends NoteContextAwareWidget {

View File

@ -1,5 +1,6 @@
import SwitchWidget from "./switch.js";
import attributeService from "../services/attributes.js";
import { t } from "../services/i18n.js";
/**
* Switch for the basic properties widget which allows the user to select whether the note is a template or not, which toggles the `#template` attribute.
@ -14,11 +15,11 @@ export default class TemplateSwitchWidget extends SwitchWidget {
doRender() {
super.doRender();
this.$switchOnName.text("Template");
this.$switchOnButton.attr("title", "Make the note a template");
this.$switchOnName.text(t("template_switch.template"));
this.$switchOnButton.attr("title", t("template_switch.toggle-on-hint"));
this.$switchOffName.text("Template");
this.$switchOffButton.attr("title", "Remove the note as a template");
this.$switchOffButton.attr("title", t("template_switch.toggle-off-hint"));
this.$helpButton.attr("data-help-page", "template.html").show();
this.$helpButton.on('click', e => utils.openHelp($(e.target)));

View File

@ -26,6 +26,15 @@ export default class MindMapWidget extends TypeWidget {
doRender() {
this.$widget = $(TPL);
this.$content = this.$widget.find(".mind-map-container");
this.$content.on("keydown", (e) => {
/*
* Some global shortcuts interfere with the default shortcuts of the mind map,
* as defined here: https://mind-elixir.com/docs/guides/shortcuts
*/
if (e.key === "F1") {
e.stopPropagation();
}
});
super.doRender();
}

View File

@ -9,7 +9,7 @@ const TPL = `
<p>${t("max_content_width.default_description")}</p>
<div class="form-group row">
<div class="col-4">
<div class="col-6">
<label>${t("max_content_width.max_width_label")}</label>
<input type="number" min="200" step="10" class="max-content-width form-control options-number-input">
</div>

View File

@ -14,7 +14,7 @@ const TPL_ELECTRON = `
<div class="options-section">
<h4>${t('spellcheck.title')}</h4>
<p>App restart is required after change.</p>
<p>${t("spellcheck.restart-required")}</p>
<label>
<input type="checkbox" class="spell-check-enabled">

View File

@ -924,6 +924,10 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
margin: 10px;
}
.help-dropdown code {
font-variant-ligatures: none;
}
#launcher-pane .launcher-button {
font-size: 150%;
display: inline-block;

View File

@ -198,14 +198,13 @@
},
"markdown_import": {
"dialog_title": "Markdown 导入",
"modal_body_text": "由于浏览器沙箱的限制,无法直接从 JavaScript 读取剪贴板内容。请将要导入的 Markdown 文本粘贴到下面的文本框中,然后点击导入按钮",
"modal_body_text": "由于浏览器沙箱的限制,无法直接从 JavaScript 读取剪贴板内容。请将要导入的 Markdown 文本粘贴到下面的文本框中,然后点击导入按钮",
"import_button": "导入 Ctrl+回车",
"import_success": "Markdown 内容已成功导入文档。"
},
"note_type_chooser": {
"modal_title": "选择笔记类型",
"modal_body": "选择新笔记的类型或模板:",
"dropdown_trigger": "下拉触发",
"templates": "模板:"
},
"password_not_set": {
@ -238,7 +237,6 @@
"delete_all_revisions": "删除此笔记的所有历史版本",
"delete_all_button": "删除所有历史版本",
"help_title": "关于笔记历史版本的帮助",
"dropdown_trigger": "下拉触发器",
"revision_last_edited": "此历史版本上次编辑于 {{date}}",
"confirm_delete_all": "您是否要删除此笔记的所有历史版本?此操作将擦除历史版本的标题和内容,但仍将保留历史版本的元数据。",
"no_revisions": "此笔记暂无历史版本...",
@ -470,8 +468,8 @@
"to": "到",
"target_parent_note": "目标父笔记",
"on_all_matched_notes": "对于所有匹配的笔记",
"move_note_new_parent": "如果笔记只有一个父笔记,则将其移动到新父笔记(即旧位置被移除,并创建到新父笔记的位置)",
"clone_note_new_parent": "如果笔记有多个克隆/位置,则将其克隆到新父笔记(不清楚应删除哪个位置)",
"move_note_new_parent": "",
"clone_note_new_parent": "",
"nothing_will_happen": "如果笔记无法移动到目标笔记(即这会创建一个树循环),则不会发生任何事情"
},
"rename_note": {
@ -1025,8 +1023,8 @@
"title": "下拉菜单可用的MIME文件类型"
},
"vim_key_bindings": {
"use_vim_keybindings_in_code_notes": "在代码笔记中使用Vim键绑定无ex模式",
"enable_vim_keybindings": "启用Vim键绑定"
"use_vim_keybindings_in_code_notes": "",
"enable_vim_keybindings": ""
},
"wrap_lines": {
"wrap_lines_in_code_notes": "代码笔记自动换行",
@ -1194,12 +1192,13 @@
},
"spellcheck": {
"title": "拼写检查",
"description": "这些选项仅适用于桌面版本,浏览器将使用其原生的拼写检查功能。更改后需要重启应用。",
"description": "这些选项仅适用于桌面版本,浏览器将使用其原生的拼写检查功能。",
"enable": "启用拼写检查",
"language_code_label": "语言代码",
"language_code_placeholder": "例如 \"en-US\", \"de-AT\"",
"multiple_languages_info": "多种语言可以用逗号分隔,例如 \"en-US, de-DE, cs\"。拼写检查选项的更改将在应用重启后生效。",
"available_language_codes_label": "可用的语言代码:"
"multiple_languages_info": "多种语言可以用逗号分隔,例如 \"en-US, de-DE, cs\"。",
"available_language_codes_label": "可用的语言代码:",
"restart-required": "拼写检查选项的更改将在应用重启后生效。"
},
"sync_2": {
"config_title": "同步配置",

View File

@ -205,13 +205,12 @@
"note_type_chooser": {
"modal_title": "Choose note type",
"modal_body": "Choose note type / template of the new note:",
"dropdown_trigger": "Dropdown trigger",
"templates": "Templates:"
},
"password_not_set": {
"title": "Password is not set",
"body1": "Protected notes are encrypted using a user password, but password has not been set yet.",
"body2": "To be able to protect notes, click <a class=\"open-password-options-button\" href=\"javascript:\">here</a> to open the Options dialog and set your password.</a>"
"body2": "To be able to protect notes, click <a class=\"open-password-options-button\" href=\"javascript:\">here</a> to open the Options dialog and set your password."
},
"prompt": {
"title": "Prompt",
@ -229,7 +228,7 @@
"title": "Recent changes",
"erase_notes_button": "Erase deleted notes now",
"deleted_notes_message": "Deleted notes have been erased.",
"no_changes_message": "No changes yet ...",
"no_changes_message": "No changes yet...",
"undelete_link": "undelete",
"confirm_undelete": "Do you want to undelete this note and its sub-notes?"
},
@ -238,7 +237,6 @@
"delete_all_revisions": "Delete all revisions of this note",
"delete_all_button": "Delete all revisions",
"help_title": "Help on Note revisions",
"dropdown_trigger": "Dropdown trigger",
"revision_last_edited": "This revision was last edited on {{date}}",
"confirm_delete_all": "Do you want to delete all revisions of this note? This action will erase revision title and content, but still preserve revision metadata.",
"no_revisions": "No revisions for this note yet...",
@ -256,7 +254,7 @@
"preview_not_available": "Preview isn't available for this note type."
},
"sort_child_notes": {
"sort_children_by": "Sort children by ...",
"sort_children_by": "Sort children by...",
"sorting_criteria": "Sorting criteria",
"title": "title",
"date_created": "date created",
@ -470,8 +468,8 @@
"to": "to",
"target_parent_note": "target parent note",
"on_all_matched_notes": "On all matched notes",
"move_note_new_parent": "move note to the new parent if note has only one parent (i.e. the old placement is removed and new placement into the new parent is created)",
"clone_note_new_parent": "clone note to the new parent if note has multiple clones/placements (it's not clear which placement should be removed)",
"move_note_new_parent": "move note to the new parent if note has only one parent (i.e. the old branch is removed and new branch into the new parent is created)",
"clone_note_new_parent": "clone note to the new parent if note has multiple clones/branches (it's not clear which branch should be removed)",
"nothing_will_happen": "nothing will happen if note cannot be moved to the target note (i.e. this would create a tree cycle)"
},
"rename_note": {
@ -752,7 +750,7 @@
"promoted_attributes": "Promoted Attributes",
"url_placeholder": "http://website...",
"open_external_link": "Open external link",
"unknown_label_type": "Unknown labelType '{{type}}'",
"unknown_label_type": "Unknown label type '{{type}}'",
"unknown_attribute_type": "Unknown attribute type '{{type}}'",
"add_new_attribute": "Add new attribute",
"remove_this_attribute": "Remove this attribute"
@ -851,7 +849,7 @@
},
"search_string": {
"title_column": "Search string:",
"placeholder": "fulltext keywords, #tag = value ...",
"placeholder": "fulltext keywords, #tag = value...",
"search_syntax": "Search syntax",
"also_see": "also see",
"complete_help": "complete help on search syntax",
@ -1028,8 +1026,8 @@
"title": "Available MIME types in the dropdown"
},
"vim_key_bindings": {
"use_vim_keybindings_in_code_notes": "Use vim keybindings in code notes (no ex mode)",
"enable_vim_keybindings": "Enable Vim Keybindings"
"use_vim_keybindings_in_code_notes": "Vim keybindings",
"enable_vim_keybindings": "Enable Vim keybindings in code notes (no ex mode)"
},
"wrap_lines": {
"wrap_lines_in_code_notes": "Wrap lines in code notes",
@ -1083,7 +1081,7 @@
"save_button": "Save"
},
"tray": {
"title": "Tray",
"title": "System Tray",
"enable_tray": "Enable tray (Trilium needs to be restarted for this change to take effect)"
},
"heading_style": {
@ -1200,12 +1198,13 @@
},
"spellcheck": {
"title": "Spell Check",
"description": "These options apply only for desktop builds, browsers will use their own native spell check. App restart is required after change.",
"description": "These options apply only for desktop builds, browsers will use their own native spell check.",
"enable": "Enable spellcheck",
"language_code_label": "Language code(s)",
"language_code_placeholder": "for example \"en-US\", \"de-AT\"",
"multiple_languages_info": "Multiple languages can be separated by comma, e.g. \"en-US, de-DE, cs\". Changes to the spell check options will take effect after application restart.",
"available_language_codes_label": "Available language codes:"
"multiple_languages_info": "Multiple languages can be separated by comma, e.g. \"en-US, de-DE, cs\". ",
"available_language_codes_label": "Available language codes:",
"restart-required": "Changes to the spell check options will take effect after application restart."
},
"sync_2": {
"config_title": "Sync Configuration",
@ -1245,5 +1244,79 @@
"note_is_editable": "Note is editable if it's not too long.",
"note_is_read_only": "Note is read-only, but can be edited with a button click.",
"note_is_always_editable": "Note is always editable, regardless of its length."
}
},
"note-map": {
"button-link-map": "Link Map",
"button-tree-map": "Tree map"
},
"tree-context-menu": {
"open-in-a-new-tab": "Open in a new tab",
"open-in-a-new-split": "Open in a new split",
"insert-note-after": "Insert note after",
"insert-child-note": "Insert child note",
"delete": "Delete",
"search-in-subtree": "Search in subtree",
"edit-branch-prefix": "Edit branch prefix",
"advanced": "Advanced",
"expand-subtree": "Expand subtree",
"collapse-subtree": "Collapse subtree",
"sort-by": "Sort by...",
"recent-changes-in-subtree": "Recent changes in subtree",
"convert-to-attachment": "Convert to attachment",
"copy-note-path-to-clipboard": "Copy note path to clipboard",
"protect-subtree": "Protect subtree",
"unprotect-subtree": "Unprotect subtree",
"copy-clone": "Copy / clone",
"clone-to": "Clone to...",
"cut": "Cut",
"move-to": "Move to...",
"paste-into": "Paste into",
"paste-after": "Paste after",
"duplicate-subtree": "Duplicate subtree",
"export": "Export",
"import-into-note": "Import into note",
"apply-bulk-actions": "Apply bulk actions"
},
"shared_info": {
"shared_publicly": "This note is shared publicly on",
"shared_locally": "This note is shared locally on",
"help_link": "For help visit <a href=\"https://triliumnext.github.io/Docs/Wiki/sharing.html\">wiki</a>."
},
"note_types": {
"text": "Text",
"code": "Code",
"saved-search": "Saved Search",
"relation-map": "Relation Map",
"note-map": "Note Map",
"render-note": "Render Note",
"book": "Book",
"mermaid-diagram": "Mermaid Diagram",
"canvas": "Canvas",
"web-view": "Web View",
"mind-map": "Mind Map",
"file": "File",
"image": "Image",
"launcher": "Launcher",
"doc": "Doc",
"widget": "Widget"
},
"protect_note": {
"toggle-on": "Protect the note",
"toggle-off": "Unprotect the note",
"toggle-on-hint": "Note is not protected, click to make it protected",
"toggle-off-hint": "Note is protected, click to make it unprotected"
},
"shared_switch": {
"shared": "Shared",
"toggle-on-title": "Share the note",
"toggle-off-title": "Unshare the note",
"shared-branch": "This note exists only as a shared note, unsharing would delete it. Do you want to continue and thus delete this note?",
"inherited": "Note cannot be unshared here because it is shared through inheritance from an ancestor."
},
"template_switch": {
"template": "Template",
"toggle-on-hint": "Make the note a template",
"toggle-off-hint": "Remove the note as a template"
},
"open-help-page": "Open help page"
}

View File

@ -132,7 +132,7 @@
"pasteNotes": "pegar notas como subnotas en la nota activa (que se puede mover o clonar dependiendo de si se copió o cortó en el portapapeles)",
"deleteNotes": "eliminar nota/subárbol",
"editingNotes": "Editando notas",
"editNoteTitle": "",
"editNoteTitle": "en el panel de árbol cambiará del panel de árbol al título de la nota. Ingresar desde el título de la nota cambiará el foco al editor de texto. <kbd>Ctrl+.</kbd> cambiará de nuevo del editor al panel de árbol",
"createEditLink": "crear/editar enlace externo",
"createInternalLink": "crear enlace interno",
"followLink": "siga el enlace debajo del cursor",
@ -205,13 +205,12 @@
"note_type_chooser": {
"modal_title": "Elija el tipo de nota",
"modal_body": "Elija el tipo de nota/plantilla de la nueva nota:",
"dropdown_trigger": "Activador desplegable",
"templates": "Plantillas:"
},
"password_not_set": {
"title": "La contraseña no está establecida",
"body1": "Las notas protegidas se cifran mediante una contraseña de usuario, pero la contraseña aún no se ha establecido.",
"body2": "Para poder proteger notas, dé clic <a class=\"open-password-options-button\" href=\"javascript:\">aquí</a> para abrir el diálogo de Opciones y establecer tu contraseña.</a>"
"body2": "Para poder proteger notas, dé clic <a class=\"open-password-options-button\" href=\"javascript:\">aquí</a> para abrir el diálogo de Opciones y establecer tu contraseña."
},
"prompt": {
"title": "Aviso",
@ -238,7 +237,6 @@
"delete_all_revisions": "Eliminar todas las revisiones de esta nota.",
"delete_all_button": "Eliminar todas las revisiones",
"help_title": "Ayuda sobre revisiones de notas",
"dropdown_trigger": "Activador desplegable",
"revision_last_edited": "Esta revisión se editó por última vez en {{date}}",
"confirm_delete_all": "¿Quiere eliminar todas las revisiones de esta nota? Esta acción borrará el título y el contenido de la revisión, pero aún conservará los metadatos de la revisión.",
"no_revisions": "Aún no hay revisiones para esta nota...",
@ -470,15 +468,15 @@
"to": "a",
"target_parent_note": "nota padre objetivo",
"on_all_matched_notes": "En todas las notas coincidentes",
"move_note_new_parent": "mover la nota al nuevo padre si la nota tiene solo un padre (es decir, se elimina la ubicación anterior y se crea una nueva ubicación en el nuevo padre)",
"clone_note_new_parent": "clonar nota al nuevo padre si la nota tiene múltiples clones/ubicaciones (no está claro qué ubicación se debe eliminar)",
"move_note_new_parent": "",
"clone_note_new_parent": "",
"nothing_will_happen": "No pasará nada si la nota no se puede mover a la nota de destino (es decir, esto crearía un ciclo de árbol)"
},
"rename_note": {
"rename_note": "Renombrar nota",
"rename_note_title_to": "Renombrar título de la nota a",
"new_note_title": "nuevo título de nota",
"click_help_icon": "Haga clic en el icono de ayuda a la derecha para ver todas las opciones.",
"click_help_icon": "Haga clic en el icono de ayuda a la derecha para ver todas las opciones",
"evaluated_as_js_string": "El valor dado se evalúa como una cadena de JavaScript y, por lo tanto, se puede enriquecer con contenido dinámico a través de la variable <code>note</code> inyectada (se cambia el nombre de la nota). Ejemplos:",
"example_note": "<code>Nota</code>: todas las notas coincidentes son renombradas a 'Nota'",
"example_new_title": "<code>NUEVO: ${note.title}</code> - los títulos de las notas coincidentes tienen el prefijo 'NUEVO: '",
@ -647,6 +645,9 @@
"hide_floating_buttons_button": {
"button_title": "Ocultar botones"
},
"svg_export_button": {
"button_title": "Exportar diagrama como SVG"
},
"relation_map_buttons": {
"create_child_note_title": "Crear una nueva nota hijo y agregarla a este mapa de relaciones",
"reset_pan_zoom_title": "Restablecer la panorámica y el zoom a las coordenadas y ampliación iniciales",
@ -655,13 +656,13 @@
},
"zpetne_odkazy": {
"backlink": "{{count}} Vínculo de retroceso",
"backlinks": "{{count}} Vínculos de retroceso",
"backlinks": "{{count}} vínculos de retroceso",
"relation": "relación"
},
"mobile_detail_menu": {
"insert_child_note": "Insertar nota hijo",
"delete_this_note": "Eliminar esta nota",
"error_cannot_get_branch_id": "No se puede obtener el branchID del notePath '{{notePad}}'",
"error_cannot_get_branch_id": "No se puede obtener el branchID del notePath '{{notePath}}'",
"error_unrecognized_command": "Comando no reconocido {{command}}"
},
"basic_properties": {
@ -1025,8 +1026,8 @@
"title": "Tipos MIME disponibles en el menú desplegable"
},
"vim_key_bindings": {
"use_vim_keybindings_in_code_notes": "Utilizar combinaciones de teclas Vim en notas de código (no modo ex)",
"enable_vim_keybindings": "Habilitar combinaciones de teclas de Vim"
"use_vim_keybindings_in_code_notes": "",
"enable_vim_keybindings": ""
},
"wrap_lines": {
"wrap_lines_in_code_notes": "Ajustar líneas en notas de código",
@ -1045,7 +1046,7 @@
"attachment_auto_deletion_description": "Los archivos adjuntos se eliminan (y borran) automáticamente si ya no se hace referencia a ellos en su nota después de un tiempo de espera definido.",
"erase_attachments_after_x_seconds": "Borrar archivos adjuntos después de X segundos de no usarse en su nota",
"manual_erasing_description": "También puede activar el borrado manualmente (sin considerar el tiempo de espera definido anteriormente):",
"erase_unused_attachments_now": "Borrar ahora los archivos adjuntos no utilizados en la nota ",
"erase_unused_attachments_now": "Borrar ahora los archivos adjuntos no utilizados en la nota",
"unused_attachments_erased": "Los archivos adjuntos no utilizados se han eliminado."
},
"network_connections": {
@ -1080,7 +1081,7 @@
"save_button": "Guardar"
},
"tray": {
"title": "Bandeja",
"title": "Bandeja de sistema",
"enable_tray": "Habilitar bandeja (es necesario reiniciar Trilium para que este cambio surta efecto)"
},
"heading_style": {
@ -1092,11 +1093,11 @@
"highlights_list": {
"title": "Lista de aspectos destacados",
"description": "Puede personalizar la lista de aspectos destacados que se muestra en el panel derecho:",
"bold": "",
"italic": "",
"underline": "",
"color": "",
"bg_color": "",
"bold": "Texto en negrita",
"italic": "Texto en cursiva",
"underline": "Texto subrayado",
"color": "Texto con color",
"bg_color": "Texto con color de fondo",
"visibility_title": "Visibilidad de la lista de aspectos destacados",
"visibility_description": "Puede ocultar el widget de aspectos destacados por nota agregando una etiqueta #hideHighlightWidget.",
"shortcut_info": "Puede configurar un método abreviado de teclado para alternar rápidamente el panel derecho (incluidos los aspectos destacados) en Opciones -> Atajos (nombre 'toggleRightPane')."
@ -1197,12 +1198,13 @@
},
"spellcheck": {
"title": "Revisión ortográfica",
"description": "Estas opciones se aplican sólo para compilaciones de escritorio; los navegadores utilizarán su corrector ortográfico nativo. Es necesario reiniciar la aplicación después del cambio.",
"description": "Estas opciones se aplican sólo para compilaciones de escritorio; los navegadores utilizarán su corrector ortográfico nativo.",
"enable": "Habilitar corrector ortográfico",
"language_code_label": "Código(s) de idioma",
"language_code_placeholder": "por ejemplo \"en-US\", \"de-AT\"",
"multiple_languages_info": "Múltiples idiomas se pueden separar por coma, por ejemplo \"en-US, de-DE, cs \". Los cambios en las opciones de corrección ortográfica entrarán en vigor después del reinicio de la aplicación.",
"available_language_codes_label": "Códigos de idioma disponibles:"
"multiple_languages_info": "Múltiples idiomas se pueden separar por coma, por ejemplo \"en-US, de-DE, cs\".",
"available_language_codes_label": "Códigos de idioma disponibles:",
"restart-required": "Los cambios en las opciones de corrección ortográfica entrarán en vigor después del reinicio de la aplicación."
},
"sync_2": {
"config_title": "Configuración de sincronización",

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
export default {
buildDate: "2024-08-09T22:05:59Z",
buildRevision: "2a5c444eff3eb99389339716ea8bfc989be90ecd"
buildDate: "2024-09-07T18:36:34Z",
buildRevision: "7c0d6930fa8f20d269dcfbcbc8f636a25f6bb9a7"
};

31
src/services/i18n.ts Normal file
View File

@ -0,0 +1,31 @@
import i18next from "i18next";
import Backend from "i18next-fs-backend";
import options from "./options.js";
import sql_init from "./sql_init.js";
export async function initializeTranslations() {
// Initialize translations
await i18next.use(Backend).init({
lng: await getCurrentLanguage(),
fallbackLng: "en",
ns: "server",
backend: {
loadPath: "translations/{{lng}}/{{ns}}.json"
},
debug: true
});
}
function getCurrentLanguage() {
let language;
if (sql_init.isDbInitialized()) {
language = options.getOption("locale");
}
if (!language) {
console.info("Language option not found, falling back to en.");
language = "en";
}
return language;
}

View File

@ -4,6 +4,7 @@ import optionService from "./options.js";
import log from "./log.js";
import utils from "./utils.js";
import { KeyboardShortcut } from './keyboard_actions_interface.js';
import { t } from "i18next";
const isMac = process.platform === "darwin";
const isElectron = utils.isElectron();
@ -19,7 +20,7 @@ const isElectron = utils.isElectron();
const DEFAULT_KEYBOARD_ACTIONS: KeyboardShortcut[] = [
{
separator: "Note navigation"
separator: t("keyboard_actions.note-navigation")
},
{
actionName: "backInNoteHistory",
@ -36,7 +37,7 @@ const DEFAULT_KEYBOARD_ACTIONS: KeyboardShortcut[] = [
{
actionName: "jumpToNote",
defaultShortcuts: ["CommandOrControl+J"],
description: 'Open "Jump to note" dialog',
description: t("keyboard_actions.open-jump-to-note-dialog"),
scope: "window"
},
{
@ -52,37 +53,37 @@ const DEFAULT_KEYBOARD_ACTIONS: KeyboardShortcut[] = [
{
actionName: "searchInSubtree",
defaultShortcuts: ["CommandOrControl+Shift+S"],
description: "Search for notes in the active note's subtree",
description: t("keyboard_actions.search-in-subtree"),
scope: "note-tree"
},
{
actionName: "expandSubtree",
defaultShortcuts: [],
description: "Expand subtree of current note",
description: t("keyboard_actions.expand-subtree"),
scope: "note-tree"
},
{
actionName: "collapseTree",
defaultShortcuts: ["Alt+C"],
description: "Collapses the complete note tree",
description: t("keyboard_actions.collapse-tree"),
scope: "window"
},
{
actionName: "collapseSubtree",
defaultShortcuts: ["Alt+-"],
description: "Collapses subtree of current note",
description: t("keyboard_actions.collapse-subtree"),
scope: "note-tree"
},
{
actionName: "sortChildNotes",
defaultShortcuts: ["Alt+S"],
description: "Sort child notes",
description: t("keyboard_actions.sort-child-notes"),
scope: "note-tree"
},
{
separator: "Creating and moving notes"
separator: t("keyboard_actions.creating-and-moving-notes")
},
{
actionName: "createNoteAfter",
@ -97,50 +98,50 @@ const DEFAULT_KEYBOARD_ACTIONS: KeyboardShortcut[] = [
{
actionName: "createNoteIntoInbox",
defaultShortcuts: ["global:CommandOrControl+Alt+P"],
description: "Create and open in the inbox (if defined) or day note",
description: t("keyboard_actions.create-note-into-inbox"),
scope: "window"
},
{
actionName: "deleteNotes",
defaultShortcuts: ["Delete"],
description: "Delete note",
description: t("keyboard_actions.delete-note"),
scope: "note-tree"
},
{
actionName: "moveNoteUp",
defaultShortcuts: isMac ? ["Alt+Up"] : ["CommandOrControl+Up"],
description: "Move note up",
description: t("keyboard_actions.move-note-up"),
scope: "note-tree"
},
{
actionName: "moveNoteDown",
defaultShortcuts: isMac ? ["Alt+Down"] : ["CommandOrControl+Down"],
description: "Move note down",
description: t("keyboard_actions.move-note-down"),
scope: "note-tree"
},
{
actionName: "moveNoteUpInHierarchy",
defaultShortcuts: isMac ? ["Alt+Left"] : ["CommandOrControl+Left"],
description: "Move note up in hierarchy",
description: t("keyboard_actions.move-note-up-in-hierarchy"),
scope: "note-tree"
},
{
actionName: "moveNoteDownInHierarchy",
defaultShortcuts: isMac ? ["Alt+Right"] : ["CommandOrControl+Right"],
description: "Move note down in hierarchy",
description: t("keyboard_actions.move-note-down-in-hierarchy"),
scope: "note-tree"
},
{
actionName: "editNoteTitle",
defaultShortcuts: ["Enter"],
description: "Jump from tree to the note detail and edit title",
description: t("keyboard_actions.edit-note-title"),
scope: "note-tree"
},
{
actionName: "editBranchPrefix",
defaultShortcuts: ["F2"],
description: "Show Edit branch prefix dialog",
scope: "window"
description: t("keyboard_actions.edit-branch-prefix"),
scope: "note-tree"
},
{
actionName: "cloneNotesTo",
@ -154,399 +155,398 @@ const DEFAULT_KEYBOARD_ACTIONS: KeyboardShortcut[] = [
},
{
separator: "Note clipboard"
separator: t("keyboard_actions.note-clipboard")
},
{
actionName: "copyNotesToClipboard",
defaultShortcuts: ["CommandOrControl+C"],
description: "Copy selected notes to the clipboard",
description: t("keyboard_actions.copy-notes-to-clipboard"),
scope: "note-tree"
},
{
actionName: "pasteNotesFromClipboard",
defaultShortcuts: ["CommandOrControl+V"],
description: "Paste notes from the clipboard into active note",
description: t("keyboard_actions.paste-notes-from-clipboard"),
scope: "note-tree"
},
{
actionName: "cutNotesToClipboard",
defaultShortcuts: ["CommandOrControl+X"],
description: "Cut selected notes to the clipboard",
description: t("keyboard_actions.cut-notes-to-clipboard"),
scope: "note-tree"
},
{
actionName: "selectAllNotesInParent",
defaultShortcuts: ["CommandOrControl+A"],
description: "Select all notes from the current note level",
description: t("keyboard_actions.select-all-notes-in-parent"),
scope: "note-tree"
},
{
actionName: "addNoteAboveToSelection",
defaultShortcuts: ["Shift+Up"],
description: "Add note above to the selection",
description: t("keyboard_actions.add-note-above-to-the-selection"),
scope: "note-tree"
},
{
actionName: "addNoteBelowToSelection",
defaultShortcuts: ["Shift+Down"],
description: "Add note above to the selection",
description: t("keyboard_actions.add-note-below-to-selection"),
scope: "note-tree"
},
{
actionName: "duplicateSubtree",
defaultShortcuts: [],
description: "Duplicate subtree",
description: t("keyboard_actions.duplicate-subtree"),
scope: "note-tree"
},
{
separator: "Tabs & Windows"
separator: t("keyboard_actions.tabs-and-windows")
},
{
actionName: "openNewTab",
defaultShortcuts: isElectron ? ["CommandOrControl+T"] : [],
description: "Opens new tab",
description: t("keyboard_actions.open-new-tab"),
scope: "window"
},
{
actionName: "closeActiveTab",
defaultShortcuts: isElectron ? ["CommandOrControl+W"] : [],
description: "Closes active tab",
description: t("keyboard_actions.close-active-tab"),
scope: "window"
},
{
actionName: "reopenLastTab",
defaultShortcuts: isElectron ? ["CommandOrControl+Shift+T"] : [],
description: "Reopens the last closed tab",
description: t("keyboard_actions.reopen-last-tab"),
scope: "window"
},
{
actionName: "activateNextTab",
defaultShortcuts: isElectron ? ["CommandOrControl+Tab", "CommandOrControl+PageDown"] : [],
description: "Activates tab on the right",
description: t("keyboard_actions.activate-next-tab"),
scope: "window"
},
{
actionName: "activatePreviousTab",
defaultShortcuts: isElectron ? ["CommandOrControl+Shift+Tab", "CommandOrControl+PageUp"] : [],
description: "Activates tab on the left",
description: t("keyboard_actions.activate-previous-tab"),
scope: "window"
},
{
actionName: "openNewWindow",
defaultShortcuts: [],
description: "Open new empty window",
description: t("keyboard_actions.open-new-window"),
scope: "window"
},
{
actionName: "toggleTray",
defaultShortcuts: [],
description: "Shows/hides the application from the system tray",
description: t("keyboard_actions.toggle-tray"),
scope: "window"
},
{
actionName: "firstTab",
defaultShortcuts: ["CommandOrControl+1"],
description: "Activates the first tab in the list",
description: t("keyboard_actions.first-tab"),
scope: "window"
},
{
actionName: "secondTab",
defaultShortcuts: ["CommandOrControl+2"],
description: "Activates the second tab in the list",
description: t("keyboard_actions.second-tab"),
scope: "window"
},
{
actionName: "thirdTab",
defaultShortcuts: ["CommandOrControl+3"],
description: "Activates the third tab in the list",
description: t("keyboard_actions.third-tab"),
scope: "window"
},
{
actionName: "fourthTab",
defaultShortcuts: ["CommandOrControl+4"],
description: "Activates the fourth tab in the list",
description: t("keyboard_actions.fourth-tab"),
scope: "window"
},
{
actionName: "fifthTab",
defaultShortcuts: ["CommandOrControl+5"],
description: "Activates the fifth tab in the list",
description: t("keyboard_actions.fifth-tab"),
scope: "window"
},
{
actionName: "sixthTab",
defaultShortcuts: ["CommandOrControl+6"],
description: "Activates the sixth tab in the list",
description: t("keyboard_actions.sixth-tab"),
scope: "window"
},
{
actionName: "seventhTab",
defaultShortcuts: ["CommandOrControl+7"],
description: "Activates the seventh tab in the list",
description: t("keyboard_actions.seventh-tab"),
scope: "window"
},
{
actionName: "eigthTab",
defaultShortcuts: ["CommandOrControl+8"],
description: "Activates the eighth tab in the list",
description: t("keyboard_actions.eight-tab"),
scope: "window"
},
{
actionName: "ninthTab",
defaultShortcuts: ["CommandOrControl+9"],
description: "Activates the ninth tab in the list",
description: t("keyboard_actions.ninth-tab"),
scope: "window"
},
{
actionName: "lastTab",
defaultShortcuts: [],
description: "Activates the last tab in the list",
description: t("keyboard_actions.last-tab"),
scope: "window"
},
{
separator: "Dialogs"
separator: t("keyboard_actions.dialogs")
},
{
actionName: "showNoteSource",
defaultShortcuts: [],
description: "Shows Note Source dialog",
description: t("keyboard_actions.show-note-source"),
scope: "window"
},
{
actionName: "showOptions",
defaultShortcuts: [],
description: "Shows Options dialog",
description: t("keyboard_actions.show-options"),
scope: "window"
},
{
actionName: "showRevisions",
defaultShortcuts: [],
description: "Shows Note Revisions dialog",
description: t("keyboard_actions.show-revisions"),
scope: "window"
},
{
actionName: "showRecentChanges",
defaultShortcuts: [],
description: "Shows Recent Changes dialog",
description: t("keyboard_actions.show-recent-changes"),
scope: "window"
},
{
actionName: "showSQLConsole",
defaultShortcuts: ["Alt+O"],
description: "Shows SQL Console dialog",
description: t("keyboard_actions.show-sql-console"),
scope: "window"
},
{
actionName: "showBackendLog",
defaultShortcuts: [],
description: "Shows Backend Log dialog",
description: t("keyboard_actions.show-backend-log"),
scope: "window"
},
{
actionName: "showHelp",
defaultShortcuts: ["F1"],
description: "Shows built-in Help / cheatsheet",
description: t("keyboard_actions.show-help"),
scope: "window"
},
{
separator: "Text note operations"
separator: t("keyboard_actions.text-note-operations")
},
{
actionName: "addLinkToText",
defaultShortcuts: ["CommandOrControl+L"],
description: "Open dialog to add link to the text",
description: t("keyboard_actions.add-link-to-text"),
scope: "text-detail"
},
{
actionName: "followLinkUnderCursor",
defaultShortcuts: ["CommandOrControl+Enter"],
description: "Follow link within which the caret is placed",
description: t("keyboard_actions.follow-link-under-cursor"),
scope: "text-detail"
},
{
actionName: "insertDateTimeToText",
defaultShortcuts: ["Alt+T"],
description: "Insert current date & time into text",
description: t("keyboard_actions.insert-date-and-time-to-text"),
scope: "text-detail"
},
{
actionName: "pasteMarkdownIntoText",
defaultShortcuts: [],
description: "Pastes Markdown from clipboard into text note",
description: t("keyboard_actions.paste-markdown-into-text"),
scope: "text-detail"
},
{
actionName: "cutIntoNote",
defaultShortcuts: [],
description: "Cuts the selection from the current note and creates subnote with the selected text",
description: t("keyboard_actions.cut-into-note"),
scope: "text-detail"
},
{
actionName: "addIncludeNoteToText",
defaultShortcuts: [],
description: "Opens the dialog to include a note",
description: t("keyboard_actions.add-include-note-to-text"),
scope: "text-detail"
},
{
actionName: "editReadOnlyNote",
defaultShortcuts: [],
description: "Edit a read-only note",
description: t("keyboard_actions.edit-readonly-note"),
scope: "window"
},
{
separator: "Attributes (labels & relations)"
separator: t("keyboard_actions.attributes-labels-and-relations")
},
{
actionName: "addNewLabel",
defaultShortcuts: ["Alt+L"],
description: "Create new label",
description: t("keyboard_actions.add-new-label"),
scope: "window"
},
{
actionName: "addNewRelation",
defaultShortcuts: ["Alt+R"],
description: "Create new relation",
description: t("keyboard_actions.create-new-relation"),
scope: "window"
},
{
separator: "Ribbon tabs"
separator: t("keyboard_actions.ribbon-tabs")
},
{
actionName: "toggleRibbonTabBasicProperties",
defaultShortcuts: [],
description: "Toggle Basic Properties",
description: t("keyboard_actions.toggle-basic-properties"),
scope: "window"
},
{
actionName: "toggleRibbonTabBookProperties",
defaultShortcuts: [],
description: "Toggle Book Properties",
description: t("keyboard_actions.toggle-book-properties"),
scope: "window"
},
{
actionName: "toggleRibbonTabFileProperties",
defaultShortcuts: [],
description: "Toggle File Properties",
description: t("keyboard_actions.toggle-file-properties"),
scope: "window"
},
{
actionName: "toggleRibbonTabImageProperties",
defaultShortcuts: [],
description: "Toggle Image Properties",
description: t("keyboard_actions.toggle-image-properties"),
scope: "window"
},
{
actionName: "toggleRibbonTabOwnedAttributes",
defaultShortcuts: ["Alt+A"],
description: "Toggle Owned Attributes",
description: t("keyboard_actions.toggle-owned-attributes"),
scope: "window"
},
{
actionName: "toggleRibbonTabInheritedAttributes",
defaultShortcuts: [],
description: "Toggle Inherited Attributes",
description: t("keyboard_actions.toggle-inherited-attributes"),
scope: "window"
},
{
actionName: "toggleRibbonTabPromotedAttributes",
defaultShortcuts: [],
description: "Toggle Promoted Attributes",
description: t("keyboard_actions.toggle-promoted-attributes"),
scope: "window"
},
{
actionName: "toggleRibbonTabNoteMap",
defaultShortcuts: [],
description: "Toggle Link Map",
description: t("keyboard_actions.toggle-link-map"),
scope: "window"
},
{
actionName: "toggleRibbonTabNoteInfo",
defaultShortcuts: [],
description: "Toggle Note Info",
description: t("keyboard_actions.toggle-note-info"),
scope: "window"
},
{
actionName: "toggleRibbonTabNotePaths",
defaultShortcuts: [],
description: "Toggle Note Paths",
description: t("keyboard_actions.toggle-note-paths"),
scope: "window"
},
{
actionName: "toggleRibbonTabSimilarNotes",
defaultShortcuts: [],
description: "Toggle Similar Notes",
description: t("keyboard_actions.toggle-similar-notes"),
scope: "window"
},
{
separator: "Other"
separator: t("keyboard_actions.other")
},
{
actionName: "toggleRightPane",
defaultShortcuts: [],
description: "Toggle the display of the right pane, which includes Table of Contents and Highlights",
description: t("keyboard_actions.toggle-right-pane"),
scope: "window"
},
{
actionName: "printActiveNote",
defaultShortcuts: [],
description: "Print active note",
description: t("keyboard_actions.print-active-note"),
scope: "window"
},
{
actionName: "openNoteExternally",
defaultShortcuts: [],
description: "Open note as a file with default application",
description: t("keyboard_actions.open-note-externally"),
scope: "window"
},
{
actionName: "renderActiveNote",
defaultShortcuts: [],
description: "Render (re-render) active note",
description: t("keyboard_actions.render-active-note"),
scope: "window"
},
{
actionName: "runActiveNote",
defaultShortcuts: ["CommandOrControl+Enter"],
description: "Run active JavaScript (frontend/backend) code note",
description: t("keyboard_actions.run-active-note"),
scope: "code-detail"
},
{
actionName: "toggleNoteHoisting",
defaultShortcuts: ["Alt+H"],
description: "Toggles note hoisting of active note",
description: t("keyboard_actions.toggle-note-hoisting"),
scope: "window"
},
{
actionName: "unhoist",
defaultShortcuts: ["Alt+U"],
description: "Unhoist from anywhere",
description: t("keyboard_actions.unhoist"),
scope: "window"
},
{
actionName: "reloadFrontendApp",
defaultShortcuts: ["F5", "CommandOrControl+R"],
description: "Reload frontend App",
description: t("keyboard_actions.reload-frontend-app"),
scope: "window"
},
{
actionName: "openDevTools",
defaultShortcuts: isElectron ? ["CommandOrControl+Shift+I"] : [],
description: "Open dev tools",
description: t("keyboard_actions.open-dev-tools"),
scope: "window"
},
{
@ -557,43 +557,43 @@ const DEFAULT_KEYBOARD_ACTIONS: KeyboardShortcut[] = [
{
actionName: "toggleLeftPane",
defaultShortcuts: [],
description: "Toggle left (note tree) panel",
description: t("keyboard_actions.toggle-left-note-tree-panel"),
scope: "window"
},
{
actionName: "toggleFullscreen",
defaultShortcuts: ["F11"],
description: "Toggle full screen",
description: t("keyboard_actions.toggle-full-screen"),
scope: "window"
},
{
actionName: "zoomOut",
defaultShortcuts: isElectron ? ["CommandOrControl+-"] : [],
description: "Zoom Out",
description: t("keyboard_actions.zoom-out"),
scope: "window"
},
{
actionName: "zoomIn",
description: "Zoom In",
description: t("keyboard_actions.zoom-in"),
defaultShortcuts: isElectron ? ["CommandOrControl+="] : [],
scope: "window"
},
{
actionName: "zoomReset",
description: "Reset zoom level",
description: t("keyboard_actions.reset-zoom-level"),
defaultShortcuts: isElectron ? ["CommandOrControl+0"] : [],
scope: "window"
},
{
actionName: "copyWithoutFormatting",
defaultShortcuts: ["CommandOrControl+Alt+C"],
description: "Copy selected text without formatting",
description: t("keyboard_actions.copy-without-formatting"),
scope: "text-detail"
},
{
actionName: "forceSaveRevision",
defaultShortcuts: [],
description: "Force creating / saving new note revision of the active note",
description: t("keyboard_actions.force-save-revision"),
scope: "window"
}
];

View File

@ -7,7 +7,7 @@
<title>TriliumNext Notes</title>
</head>
<body class="desktop heading-style-<%= headingStyle %>">
<noscript>Trilium requires JavaScript to be enabled.</noscript>
<noscript><%= t("javascript-required") %></noscript>
<script>
// hide body to reduce flickering on the startup. This is done through JS and not CSS to not hide <noscript>

View File

@ -3,24 +3,24 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Login</title>
<title><%= t("login.title") %></title>
<link rel="apple-touch-icon" sizes="180x180" href="<%= assetPath %>/images/app-icons/ios/apple-touch-icon.png">
<link rel="shortcut icon" href="favicon.ico">
</head>
<body>
<div class="container">
<div class="col-xs-12 col-sm-10 col-md-6 col-lg-4 col-xl-4 mx-auto" style="padding-top: 25px;">
<h1>Trilium login</h1>
<h1><%= t("login.heading") %></h1>
<% if (failedAuth) { %>
<div class="alert alert-warning">
Password is incorrect. Please try again.
<%= t("login.incorrect-password") %>
</div>
<% } %>
<form action="login" method="POST">
<div class="form-group">
<label for="password">Password</label>
<label for="password"><%= t("login.password") %></label>
<div class="controls">
<input id="password" name="password" placeholder="" class="form-control" type="password">
</div>
@ -28,12 +28,12 @@
<div class="form-group">
<div class="checkbox">
<label>
<input id="remember-me" name="rememberMe" value="1" type="checkbox"> Remember me
<input id="remember-me" name="rememberMe" value="1" type="checkbox"> <%= t("login.remember-me") %>
</label>
</div>
</div>
<div class="form-group">
<button class="btn btn-success">Login</button>
<button class="btn btn-success"><%= t("login.button") %></button>
</div>
</form>
</div>

View File

@ -96,7 +96,7 @@
</style>
</head>
<body class="mobile heading-style-<%= headingStyle %>">
<noscript>Trilium requires JavaScript to be enabled.</noscript>
<noscript><%= t("javascript-required") %></noscript>
<div id="toast-container" class="d-flex flex-column justify-content-center align-items-center"></div>

View File

@ -3,14 +3,14 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Login</title>
<title><%= t("login.title") %></title>
<link rel="apple-touch-icon" sizes="180x180" href="<%= assetPath %>/images/app-icons/ios/apple-touch-icon.png">
<link rel="shortcut icon" href="favicon.ico">
</head>
<body>
<div class="container">
<div class="col-xs-12 col-sm-10 col-md-6 col-lg-4 col-xl-4 mx-auto" style="padding-top: 25px;">
<h1>Set password</h1>
<h1><%= t("set_password.heading") %></h1>
<% if (error) { %>
<div class="alert alert-warning">
@ -18,24 +18,24 @@
</div>
<% } %>
<p>Before you can start using Trilium from web, you need to set a password first. You will then use this password to login.</p>
<p><%= t("set_password.description") %></p>
<form action="set-password" method="POST">
<div class="form-group">
<label for="password">Password</label>
<label for="password"><%= t("set_password.password") %></label>
<div class="controls">
<input id="password" name="password1" placeholder="" class="form-control" type="password">
</div>
</div>
<div class="form-group">
<label for="password">Password confirmation</label>
<label for="password"><%= t("set_password.password-confirmation") %></label>
<div class="controls">
<input id="password" name="password2" placeholder="" class="form-control" type="password">
</div>
</div>
<div class="form-group">
<button class="btn btn-success">Set password</button>
<button class="btn btn-success"><%= t("set_password.button") %></button>
</div>
</form>
</div>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Setup</title>
<title><%= t("setup.title") %></title>
<style>
.lds-ring {
@ -44,10 +44,10 @@
</style>
</head>
<body>
<noscript>Trilium requires JavaScript to be enabled.</noscript>
<noscript><%= t("javascript-required") %></noscript>
<div class="container">
<div id="setup-dialog" class="col-md-12 col-lg-8 col-xl-6 mx-auto" style="padding-top: 25px; font-size: larger; display: none;">
<h1>TriliumNext Notes setup</h1>
<h1><%= t("setup.heading") %></h1>
<div class="alert alert-warning" id="alert" style="display: none;">
</div>
@ -55,22 +55,22 @@
<div id="setup-type" data-bind="visible: step() == 'setup-type'" style="margin-top: 20px;">
<div class="radio" style="margin-bottom: 15px;">
<label><input type="radio" name="setup-type" value="new-document" data-bind="checked: setupType">
I'm a new user, and I want to create a new Trilium document for my notes</label>
<%= t("setup.new-document") %></label>
</div>
<div class="radio" style="margin-bottom: 15px;">
<label><input type="radio" name="setup-type" value="sync-from-desktop" data-bind="checked: setupType">
I have a desktop instance already, and I want to set up sync with it</label>
<%= t("setup.sync-from-desktop") %></label>
</div>
<div class="radio" style="margin-bottom: 15px;">
<label><input type="radio" name="setup-type" value="sync-from-server" data-bind="checked: setupType">
I have a server instance already, and I want to set up sync with it</label>
<%= t("setup.sync-from-server") %></label>
</div>
<button type="button" data-bind="disable: !setupTypeSelected(), click: selectSetupType" class="btn btn-primary">Next</button>
<button type="button" data-bind="disable: !setupTypeSelected(), click: selectSetupType" class="btn btn-primary"><%= t("setup.next") %></button>
</div>
<div data-bind="visible: step() == 'new-document-in-progress'">
<h2>Document initialization in progress</h2>
<h2><%= t("setup.init-in-progress") %></h2>
<div style="display: flex; justify-content: flex-start; margin-top: 20px;">
<div class="lds-ring" style="margin-right: 20px;">
@ -81,61 +81,61 @@
</div>
<div style="line-height: 60px;">
<p>You will be shortly redirected to the application.</p>
<p><%= t("setup.redirecting") %></p>
</div>
</div>
</div>
<div data-bind="visible: step() == 'sync-from-desktop'">
<h2>Sync from Desktop</h2>
<h2><%= t("setup_sync-from-desktop.heading") %></h2>
<p>This setup needs to be initiated from the desktop instance:</p>
<p><%= t("setup_sync-from-desktop.description") %></p>
<ol>
<li>Open your desktop instance of TriliumNext Notes.</li>
<li>From the Trilium Menu, click Options.</li>
<li>Click on Sync tab.</li>
<li>Change server instance address to: <span id="current-host"></span> and click save.</li>
<li>Click "Test sync" button to verify connection is successful.</li>
<li>Once you've completed these steps, click <a href="/">here</a>.</li>
<li><%= t("setup_sync-from-desktop.step1") %></li>
<li><%= t("setup_sync-from-desktop.step2") %></li>
<li><%= t("setup_sync-from-desktop.step3") %></li>
<li><%- t("setup_sync-from-desktop.step4", { host: '<span id="current-host"></span>'}) %></li>
<li><%= t("setup_sync-from-desktop.step5") %></li>
<li><%- t("setup_sync-from-desktop.step6", { link: `<a href="/">${t("setup_sync-from-desktop.step6-here")}</a>` }) %></li>
</ol>
<button type="button" data-bind="click: back" class="btn btn-secondary">Back</button>
</div>
<div data-bind="visible: step() == 'sync-from-server'">
<h2>Sync from Server</h2>
<h2><%= t("setup_sync-from-server.heading") %></h2>
<p>Please enter Trilium server address and credentials below. This will download the whole Trilium document from server and setup sync to it. Depending on the document size and your connection speed, this may take a while.</p>
<p><%= t("setup_sync-from-server.instructions") %></p>
<div class="form-group">
<label for="sync-server-host">Trilium server address</label>
<input type="text" id="syncServerHost" class="form-control" data-bind="value: syncServerHost" placeholder="https://<hostname>:<port>">
<label for="sync-server-host"><%= t("setup_sync-from-server.server-host") %></label>
<input type="text" id="syncServerHost" class="form-control" data-bind="value: syncServerHost" placeholder="<%= t("setup_sync-from-server.server-host-placeholder") %>">
</div>
<div class="form-group">
<label for="sync-proxy">Proxy server (optional)</label>
<input type="text" id="sync-proxy" class="form-control" data-bind="value: syncProxy" placeholder="https://<hostname>:<port>">
<label for="sync-proxy"><%= t("setup_sync-from-server.proxy-server") %></label>
<input type="text" id="sync-proxy" class="form-control" data-bind="value: syncProxy" placeholder="<%= t("setup_sync-from-server.proxy-server-placeholder") %>">
<p><strong>Note:</strong> If you leave proxy setting blank, system proxy will be used (applies to desktop/electron build only)</p>
<p><strong><%= t("setup_sync-from-server.note") %></strong> <%= t("setup_sync-from-server.proxy-instruction") %></p>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" class="form-control" data-bind="value: password" placeholder="Password">
<label for="password"><%= t("setup_sync-from-server.password") %></label>
<input type="password" id="password" class="form-control" data-bind="value: password" placeholder="<%= t("setup_sync-from-server.password-placeholder") %>">
</div>
<button type="button" data-bind="click: back" class="btn btn-secondary">Back</button>
<button type="button" data-bind="click: back" class="btn btn-secondary"><%= t("setup_sync-from-server.back") %></button>
&nbsp;
<button type="button" data-bind="click: finish" class="btn btn-primary">Finish setup</button>
<button type="button" data-bind="click: finish" class="btn btn-primary"><%= t("setup_sync-from-server.finish-setup") %></button>
</div>
<div data-bind="visible: step() == 'sync-in-progress'">
<h2>Sync in progress</h2>
<h2><%= t("setup_sync-in-progress.heading") %></h2>
<div class="alert alert-success">Sync has been correctly set up. It will take some time for the initial sync to finish. Once it's done, you'll be redirected to the login page.</div>
<div class="alert alert-success"><%= t("setup_sync-in-progress.successful") %></div>
<div>Outstanding sync items: <strong id="outstanding-syncs">N/A</strong></div>
<div><%= t("setup_sync-in-progress.outstanding-items") %> <strong id="outstanding-syncs"><%= t("setup_sync-in-progress.outstanding-items-default") %></strong></div>
</div>
</div>
</div>

View File

@ -3,9 +3,9 @@
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="../favicon.ico">
<title>Not found</title>
<title><%= t("share_404.title") %></title>
</head>
<body>
<h1>Not found</h1>
<h1><%= t("share_404.heading") %></h1>
</body>
</html>

View File

@ -37,15 +37,15 @@
<div id="main">
<% if (note.parents[0].noteId !== '_share' && note.parents.length !== 0) { %>
<nav id="parentLink">
parent: <a href="<%= note.parents[0].shareId %>"
class="type-<%= note.parents[0].type %>"><%= note.parents[0].title %></a>
<%= t("share_page.parent") %> <a href="<%= note.parents[0].shareId %>"
class="type-<%= note.parents[0].type %>"><%= note.parents[0].title %></a>
</nav>
<% } %>
<h1 id="title"><%= note.title %></h1>
<% if (note.hasLabel("pageUrl")) { %>
<div id="noteClippedFrom">This note was originally clipped from <a href="<%= note.getLabelValue("pageUrl") %>"><%= note.getLabelValue("pageUrl") %></a></div>
<div id="noteClippedFrom"><%- t("share_page.clipped-from", { url: `<a href="${note.getLabelValue("pageUrl")}">${note.getLabelValue("pageUrl")}</a>` }) %></div>
<% } %>
<% if (!isEmpty) { %>
@ -58,7 +58,7 @@
<nav id="childLinks" class="<% if (isEmpty) { %>grid<% } else { %>list<% } %>">
<% if (!isEmpty) { %>
<hr>
<span>Child notes: </span>
<span><%= t("share_page.child-notes") %> </span>
<% } %>
<ul>
@ -76,7 +76,7 @@
</ul>
</nav>
<% } else if (isEmpty) { %>
<p>This note has no content.</p>
<p><%= t("share_page.no-content") %></p>
<% } %>
</div>

View File

@ -1,4 +1,5 @@
#!/usr/bin/env node
import app from "./app.js";
import sessionParser from "./routes/session_parser.js";
import fs from "fs";
@ -55,13 +56,15 @@ async function startTrilium() {
*/
if (utils.isElectron()) {
(await import('electron')).app.requestSingleInstanceLock();
}
}
log.info(JSON.stringify(appInfo, null, 2));
// for perf. issues it's good to know the rough configuration
const cpuInfos = (await import('os')).cpus();
if (cpuInfos && cpuInfos[0] !== undefined) { // https://github.com/zadam/trilium/pull/3957
log.info(`CPU model: ${cpuInfos[0].model}, logical cores: ${cpuInfos.length} freq: ${cpuInfos[0].speed} Mhz`); // for perf. issues it's good to know the rough configuration
const cpuModel = (cpuInfos[0].model || "").trimEnd();
log.info(`CPU model: ${cpuModel}, logical cores: ${cpuInfos.length}, freq: ${cpuInfos[0].speed} Mhz`);
}
const httpServer = startHttpServer();
@ -144,7 +147,16 @@ function startHttpServer() {
}
if (utils.isElectron()) {
import("electron").then(({ dialog }) => {
import("electron").then(({ app, dialog }) => {
// Not all situations require showing an error dialog. When Trilium is already open,
// clicking the shortcut, the software icon, or the taskbar icon, or when creating a new window,
// should simply focus on the existing window or open a new one, without displaying an error message.
if ("code" in error && error.code == 'EADDRINUSE') {
if (process.argv.includes('--new-window') || !app.requestSingleInstanceLock()) {
console.error(message);
process.exit(1);
}
}
dialog.showErrorBox("Error while initializing the server", message);
process.exit(1);
});

View File

@ -0,0 +1 @@
{}

161
translations/en/server.json Normal file
View File

@ -0,0 +1,161 @@
{
"keyboard_actions": {
"open-jump-to-note-dialog": "Open \"Jump to note\" dialog",
"search-in-subtree": "Search for notes in the active note's subtree",
"expand-subtree": "Expand subtree of current note",
"collapse-tree": "Collapses the complete note tree",
"collapse-subtree": "Collapses subtree of current note",
"sort-child-notes": "Sort child notes",
"creating-and-moving-notes": "Creating and moving notes",
"create-note-into-inbox": "Create a note in the inbox (if defined) or day note",
"delete-note": "Delete note",
"move-note-up": "Move note up",
"move-note-down": "Move note down",
"move-note-up-in-hierarchy": "Move note up in hierarchy",
"move-note-down-in-hierarchy": "Move note down in hierarchy",
"edit-note-title": "Jump from tree to the note detail and edit title",
"edit-branch-prefix": "Show Edit branch prefix dialog",
"note-clipboard": "Note clipboard",
"copy-notes-to-clipboard": "Copy selected notes to the clipboard",
"paste-notes-from-clipboard": "Paste notes from the clipboard into active note",
"cut-notes-to-clipboard": "Cut selected notes to the clipboard",
"select-all-notes-in-parent": "Select all notes from the current note level",
"add-note-above-to-the-selection": "Add note above to the selection",
"add-note-below-to-selection": "Add note above to the selection",
"duplicate-subtree": "Duplicate subtree",
"tabs-and-windows": "Tabs & Windows",
"open-new-tab": "Opens new tab",
"close-active-tab": "Closes active tab",
"reopen-last-tab": "Reopens the last closed tab",
"activate-next-tab": "Activates tab on the right",
"activate-previous-tab": "Activates tab on the left",
"open-new-window": "Open new empty window",
"toggle-tray": "Shows/hides the application from the system tray",
"first-tab": "Activates the first tab in the list",
"second-tab": "Activates the second tab in the list",
"third-tab": "Activates the third tab in the list",
"fourth-tab": "Activates the fourth tab in the list",
"fifth-tab": "Activates the fifth tab in the list",
"sixth-tab": "Activates the sixth tab in the list",
"seventh-tab": "Activates the seventh tab in the list",
"eight-tab": "Activates the eighth tab in the list",
"ninth-tab": "Activates the ninth tab in the list",
"last-tab": "Activates the last tab in the list",
"dialogs": "Dialogs",
"show-note-source": "Shows Note Source dialog",
"show-options": "Shows Options dialog",
"show-revisions": "Shows Note Revisions dialog",
"show-recent-changes": "Shows Recent Changes dialog",
"show-sql-console": "Shows SQL Console dialog",
"show-backend-log": "Shows Backend Log dialog",
"text-note-operations": "Text note operations",
"add-link-to-text": "Open dialog to add link to the text",
"follow-link-under-cursor": "Follow link within which the caret is placed",
"insert-date-and-time-to-text": "Insert current date & time into text",
"paste-markdown-into-text": "Pastes Markdown from clipboard into text note",
"cut-into-note": "Cuts the selection from the current note and creates subnote with the selected text",
"add-include-note-to-text": "Opens the dialog to include a note",
"edit-readonly-note": "Edit a read-only note",
"attributes-labels-and-relations": "Attributes (labels & relations)",
"add-new-label": "Create new label",
"create-new-relation": "Create new relation",
"ribbon-tabs": "Ribbon tabs",
"toggle-basic-properties": "Toggle Basic Properties",
"toggle-file-properties": "Toggle File Properties",
"toggle-image-properties": "Toggle Image Properties",
"toggle-owned-attributes": "Toggle Owned Attributes",
"toggle-inherited-attributes": "Toggle Inherited Attributes",
"toggle-promoted-attributes": "Toggle Promoted Attributes",
"toggle-link-map": "Toggle Link Map",
"toggle-note-info": "Toggle Note Info",
"toggle-note-paths": "Toggle Note Paths",
"toggle-similar-notes": "Toggle Similar Notes",
"other": "Other",
"toggle-right-pane": "Toggle the display of the right pane, which includes Table of Contents and Highlights",
"print-active-note": "Print active note",
"open-note-externally": "Open note as a file with default application",
"render-active-note": "Render (re-render) active note",
"run-active-note": "Run active JavaScript (frontend/backend) code note",
"toggle-note-hoisting": "Toggles note hoisting of active note",
"unhoist": "Unhoist from anywhere",
"reload-frontend-app": "Reload frontend App",
"open-dev-tools": "Open dev tools",
"toggle-left-note-tree-panel": "Toggle left (note tree) panel",
"toggle-full-screen": "Toggle full screen",
"zoom-out": "Zoom Out",
"zoom-in": "Zoom In",
"note-navigation": "Note navigation",
"reset-zoom-level": "Reset zoom level",
"copy-without-formatting": "Copy selected text without formatting",
"force-save-revision": "Force creating / saving new note revision of the active note",
"show-help": "Shows built-in Help / cheatsheet",
"toggle-book-properties": "Toggle Book Properties"
},
"login": {
"title": "Login",
"heading": "Trilium login",
"incorrect-password": "Password is incorrect. Please try again.",
"password": "Password",
"remember-me": "Remember me",
"button": "Login"
},
"set_password": {
"heading": "Set password",
"description": "Before you can start using Trilium from web, you need to set a password first. You will then use this password to login.",
"password": "Password",
"password-confirmation": "Password confirmation",
"button": "Set password"
},
"javascript-required": "Trilium requires JavaScript to be enabled.",
"setup": {
"heading": "TriliumNext Notes setup",
"new-document": "I'm a new user, and I want to create a new Trilium document for my notes",
"sync-from-desktop": "I have a desktop instance already, and I want to set up sync with it",
"sync-from-server": "I have a server instance already, and I want to set up sync with it",
"next": "Next",
"init-in-progress": "Document initialization in progress",
"redirecting": "You will be shortly redirected to the application.",
"title": "Setup"
},
"setup_sync-from-desktop": {
"heading": "Sync from Desktop",
"description": "This setup needs to be initiated from the desktop instance:",
"step1": "Open your desktop instance of TriliumNext Notes.",
"step2": "From the Trilium Menu, click Options.",
"step3": "Click on Sync category.",
"step4": "Change server instance address to: {{- host}} and click Save.",
"step5": "Click \"Test sync\" button to verify connection is successful.",
"step6": "Once you've completed these steps, click {{- link}}.",
"step6-here": "here"
},
"setup_sync-from-server": {
"heading": "Sync from Server",
"instructions": "Please enter Trilium server address and credentials below. This will download the whole Trilium document from server and setup sync to it. Depending on the document size and your connection speed, this may take a while.",
"server-host": "Trilium server address",
"server-host-placeholder": "https://<hostname>:<port>",
"proxy-server": "Proxy server (optional)",
"proxy-server-placeholder": "https://<hostname>:<port>",
"note": "Note:",
"proxy-instruction": "If you leave proxy setting blank, system proxy will be used (applies to the desktop application only)",
"password": "Password",
"password-placeholder": "Password",
"back": "Back",
"finish-setup": "Finish setup"
},
"setup_sync-in-progress": {
"heading": "Sync in progress",
"successful": "Sync has been correctly set up. It will take some time for the initial sync to finish. Once it's done, you'll be redirected to the login page.",
"outstanding-items": "Outstanding sync items:",
"outstanding-items-default": "N/A"
},
"share_404": {
"title": "Not found",
"heading": "Not found"
},
"share_page": {
"parent": "parent:",
"clipped-from": "This note was originally clipped from {{- url}}",
"child-notes": "Child notes:",
"no-content": "This note has no content."
}
}

View File

@ -0,0 +1 @@
{}

164
translations/ro/server.json Normal file
View File

@ -0,0 +1,164 @@
{
"keyboard-actions": {
"note-navigation": "Navigarea printre notițe"
},
"keyboard_actions": {
"activate-next-tab": "Activează tab-ul din dreapta",
"activate-previous-tab": "Activează tab-ul din stânga",
"add-include-note-to-text": "Deschide fereastra de includere notițe",
"add-link-to-text": "Deschide fereastra de adaugă legături în text",
"add-new-label": "Crează o nouă etichetă",
"add-note-above-to-the-selection": "Adaugă notița deasupra selecției",
"add-note-below-to-selection": "Adaugă notița deasupra selecției",
"attributes-labels-and-relations": "Atribute (etichete și relații)",
"close-active-tab": "Închide tab-ul activ",
"collapse-subtree": "Minimizează ierarhia notiței curente",
"collapse-tree": "Minimizează întreaga ierarhie de notițe",
"copy-notes-to-clipboard": "Copiază notițele selectate în clipboard",
"copy-without-formatting": "Copiază textul selectat fără formatare",
"create-new-relation": "Crează o nouă relație",
"create-note-into-inbox": "Crează o notiță și o deschide în inbox (dacă este definit) sau notița zilnică",
"cut-notes-to-clipboard": "Decupează notițele selectate în clipboard",
"creating-and-moving-notes": "Crearea și mutarea notițelor",
"cut-into-note": "Decupează selecția din notița curentă și crează o subnotiță cu textul selectat",
"delete-note": "Șterge notița",
"dialogs": "Ferestre",
"duplicate-subtree": "Dublifică subnotițele",
"edit-branch-prefix": "Afișează ecranul „Editează prefixul ramurii”",
"edit-note-title": "Sare de la arborele notițelor la detaliile notiței și editează titlul",
"edit-readonly-note": "Editează o notiță care este în modul doar în citire",
"eight-tab": "Activează cel de-al optelea tab din listă",
"expand-subtree": "Expandează ierarhia notiței curente",
"fifth-tab": "Activează cel de-al cincelea tab din listă",
"first-tab": "Activează cel primul tab din listă",
"follow-link-under-cursor": "Urmărește legătura de sub poziția cursorului",
"force-save-revision": "Forțează crearea/salvarea unei noi revizii ale notiției curente",
"fourth-tab": "Activează cel de-al patrulea tab din listă",
"insert-date-and-time-to-text": "Inserează data curentă și timpul în text",
"last-tab": "Activează ultimul tab din listă",
"move-note-down": "Mută notița mai jos",
"move-note-down-in-hierarchy": "Mută notița mai jos în ierarhie",
"move-note-up": "Mută notița mai sus",
"move-note-up-in-hierarchy": "Mută notița mai sus în ierarhie",
"ninth-tab": "Activează cel de-al nouălea tab din listă",
"note-clipboard": "Clipboard-ul notițelor",
"note-navigation": "Navigarea printre notițe",
"open-dev-tools": "Deschide uneltele de dezvoltator",
"open-jump-to-note-dialog": "Deschide ecranul „Sari la notiță”",
"open-new-tab": "Deschide un tab nou",
"open-new-window": "Deschide o nouă fereastră goală",
"open-note-externally": "Deschide notița ca un fișier utilizând aplicația implicită",
"other": "Altele",
"paste-markdown-into-text": "Lipește text Markdown din clipboard în notița de tip text",
"paste-notes-from-clipboard": "Lipește notițele din clipboard în notița activă",
"print-active-note": "Imprimă notița activă",
"reload-frontend-app": "Reîncarcă interfața grafică",
"render-active-note": "Reîmprospătează notița activă",
"reopen-last-tab": "Deschide din nou ultimul tab închis",
"reset-zoom-level": "Resetează nivelul de magnificare",
"ribbon-tabs": "Tab-urile din panglică",
"run-active-note": "Rulează notița curentă de tip JavaScript (frontend sau backend)",
"search-in-subtree": "Caută notițe în ierarhia notiței active",
"second-tab": "Activează cel de-al doilea tab din listă",
"select-all-notes-in-parent": "Selectează toate notițele din nivelul notiței curente",
"seventh-tab": "Activează cel de-al șaptelea tab din listă",
"show-backend-log": "Afișează fereastra „Log-uri din backend”",
"show-help": "Afișează informații utile",
"show-note-source": "Afișează fereastra „Sursa notiței”",
"show-options": "Afișează fereastra de opțiuni",
"show-recent-changes": "Afișează fereastra „Schimbări recente”",
"show-revisions": "Afișează fereastra „Revizii ale notiței”",
"show-sql-console": "Afișează ecranul „Consolă SQL”",
"sixth-tab": "Activează cel de-al șaselea tab din listă",
"sort-child-notes": "Ordonează subnotițele",
"tabs-and-windows": "Tab-uri și ferestre",
"text-note-operations": "Operații asupra notițelor text",
"third-tab": "Activează cel de-al treilea tab din listă",
"toggle-basic-properties": "Comută tab-ul „Proprietăți de bază”",
"toggle-book-properties": "Comută tab-ul „Proprietăți ale cărții”",
"toggle-file-properties": "Comută tab-ul „Proprietăți fișier”",
"toggle-full-screen": "Comută modul ecran complet",
"toggle-image-properties": "Comută tab-ul „Proprietăți imagini”",
"toggle-inherited-attributes": "Comută tab-ul „Atribute moștenite”",
"toggle-left-note-tree-panel": "Comută panoul din stânga (arborele notițelor)",
"toggle-link-map": "Comută harta legăturilor",
"toggle-note-hoisting": "Comută focalizarea pe notița curentă",
"toggle-note-info": "Comută tab-ul „Informații despre notiță”",
"toggle-note-paths": "Comută tab-ul „Căile notiței”",
"toggle-owned-attributes": "Comută tab-ul „Atribute proprii”",
"toggle-promoted-attributes": "Comută tab-ul „Atribute promovate”",
"toggle-right-pane": "Comută afișarea panoului din dreapta, ce include tabela de conținut și evidențieri",
"toggle-similar-notes": "Comută tab-ul „Notițe similare”",
"toggle-tray": "Afișează/ascunde aplicația din tray-ul de sistem",
"unhoist": "Defocalizează complet",
"zoom-in": "Mărește zoom-ul",
"zoom-out": "Micșorează zoom-ul"
},
"login": {
"button": "Autentifică",
"heading": "Autentificare în Trilium",
"incorrect-password": "Parola nu este corectă. Încercați din nou.",
"password": "Parolă",
"remember-me": "Ține-mă minte",
"title": "Autentificare"
},
"set_password": {
"heading": "Setare parolă",
"button": "Setează parola",
"description": "Înainte de a putea utiliza Trilium din navigator, trebuie mai întâi setată o parolă. Ulterior această parolă va fi folosită la autentificare.",
"password": "Parolă",
"password-confirmation": "Confirmarea parolei"
},
"javascript-required": "Trilium necesită JavaScript să fie activat pentru a putea funcționa.",
"setup": {
"heading": "Instalarea TriliumNext Notes",
"init-in-progress": "Se inițializează documentul",
"new-document": "Sunt un utilizator nou și doresc să creez un document Trilium pentru notițele mele",
"next": "Mai departe",
"redirecting": "În scurt timp veți fi redirecționat la aplicație.",
"sync-from-desktop": "Am deja o instanță de desktop și aș dori o sincronizare cu aceasta",
"sync-from-server": "Am deja o instanță de server și doresc o sincronizare cu aceasta",
"title": "Inițializare"
},
"setup_sync-from-desktop": {
"description": "Acești pași trebuie urmați de pe aplicația de desktop:",
"heading": "Sincronizare cu aplicația desktop",
"step1": "Deschideți aplicația TriliumNext Notes pentru desktop.",
"step2": "Din meniul Trilium, dați clic pe Opțiuni.",
"step3": "Clic pe categoria „Sincronizare”.",
"step4": "Schimbați adresa server-ului către: {{- host}} și apăsați „Salvează”.",
"step5": "Clic pe butonul „Testează sincronizarea” pentru a verifica dacă conexiunea a fost făcută cu succes.",
"step6": "După ce ați completat pașii, dați click {{- link}}.",
"step6-here": "aici"
},
"setup_sync-from-server": {
"back": "Înapoi",
"finish-setup": "Finalizează inițializarea",
"heading": "Sincronizare cu server-ul",
"instructions": "Introduceți adresa server-ului Trilium și credențialele în secțiunea de jos. Astfel se va descărca întregul document Trilium de pe server și se va configura sincronizarea cu acesta. În funcție de dimensiunea documentului și viteza rețelei, acest proces poate dura.",
"note": "De remarcat:",
"password": "Parolă",
"proxy-instruction": "Dacă lăsați câmpul de proxy nesetat, proxy-ul de sistem va fi folosit (valabil doar pentru aplicația de desktop)",
"proxy-server": "Server-ul proxy (opțional)",
"proxy-server-placeholder": "https://<sistem>:<port>",
"server-host": "Adresa server-ului Trilium",
"server-host-placeholder": "https://<sistem>:<port>",
"password-placeholder": "Parolă"
},
"setup_sync-in-progress": {
"heading": "Sincronizare în curs",
"outstanding-items": "Elemente de sincronizat:",
"outstanding-items-default": "-",
"successful": "Sincronizarea a fost configurată cu succes. Poate dura ceva timp pentru a finaliza sincronizarea inițială. După efectuarea ei se va redirecționa către pagina de autentificare."
},
"share_404": {
"heading": "Pagină negăsită",
"title": "Pagină negăsită"
},
"share_page": {
"child-notes": "Subnotițe:",
"clipped-from": "Această notiță a fost decupată inițial de pe {{- url}}",
"no-content": "Această notiță nu are conținut.",
"parent": "părinte:"
}
}