You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-12-23 23:33:01 +02:00
Compare commits
106 Commits
mobile_plu
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
175a1b7a64 | ||
|
|
d5a60ba2d7 | ||
|
|
a07985da98 | ||
|
|
78ffc0bc23 | ||
|
|
e041169300 | ||
|
|
41dc96b441 | ||
|
|
d448b8bd4e | ||
|
|
5855748e06 | ||
|
|
4e2d36648e | ||
|
|
f807a0179d | ||
|
|
b3801b333d | ||
|
|
c3e08237fd | ||
|
|
b406f05241 | ||
|
|
2cbee6d8af | ||
|
|
c859ad48c1 | ||
|
|
1141b1c2a1 | ||
|
|
39c118be90 | ||
|
|
f9ac4e112b | ||
|
|
87e51aa8e6 | ||
|
|
41fdc0d44d | ||
|
|
a754a8d772 | ||
|
|
41d0363fd0 | ||
|
|
2a4c7a334e | ||
|
|
df1b0a96f4 | ||
|
|
0030681cb4 | ||
|
|
e7014492c5 | ||
|
|
4804c1c0c3 | ||
|
|
270d96ad07 | ||
|
|
5ed3d94faa | ||
|
|
d0e943630d | ||
|
|
406e933407 | ||
|
|
7108a4243d | ||
|
|
135e2e4a21 | ||
|
|
c68c0bf501 | ||
|
|
cf3d86698d | ||
|
|
3251c4c40e | ||
|
|
bd5e0fd42a | ||
|
|
7d0b7122f0 | ||
|
|
c50052ac04 | ||
|
|
357c23b588 | ||
|
|
eca1afb6d5 | ||
|
|
85eddbfe22 | ||
|
|
c6c2733726 | ||
|
|
5d87b4ca3e | ||
|
|
89f550ca48 | ||
|
|
9e55d90736 | ||
|
|
8d0d9b58de | ||
|
|
ac5e484d4e | ||
|
|
bce18a1614 | ||
|
|
950b16370f | ||
|
|
4337e2b79a | ||
|
|
90d75ce80e | ||
|
|
72d34788dc | ||
|
|
6a2e6173ab | ||
|
|
65bb9fa3c4 | ||
|
|
90e1502e73 | ||
|
|
3cc990e1a2 | ||
|
|
10fd8454f7 | ||
|
|
56d7030222 | ||
|
|
8696052e27 | ||
|
|
5f7e130ff9 | ||
|
|
434c890686 | ||
|
|
5ab1b0bfd0 | ||
|
|
b9f632b634 | ||
|
|
ae8f32e6b4 | ||
|
|
ce8470ee7c | ||
|
|
3b1a726a23 | ||
|
|
3d4740203f | ||
|
|
7a74271e6a | ||
|
|
2cfae43fce | ||
|
|
a143b980ee | ||
|
|
329c385358 | ||
|
|
1543c651aa | ||
|
|
9cdaff4f1e | ||
|
|
8e3247221a | ||
|
|
ad975a473f | ||
|
|
9a8c0e9813 | ||
|
|
9d16dd22be | ||
|
|
c0501fc4e0 | ||
|
|
1acbb5dc9a | ||
|
|
2f6e146841 | ||
|
|
ba2bfa5b5c | ||
|
|
95ca89bf5b | ||
|
|
16d8a78d8a | ||
|
|
f116504e88 | ||
|
|
4d0b6ae382 | ||
|
|
13c4eba3af | ||
|
|
9756f64c11 | ||
|
|
807384cfac | ||
|
|
2329e321ec | ||
|
|
6c2e0d9262 | ||
|
|
887c271853 | ||
|
|
ea7c7f6447 | ||
|
|
29931c05ad | ||
|
|
17c227024e | ||
|
|
406a1496db | ||
|
|
c8180b91e0 | ||
|
|
1978929114 | ||
|
|
3e7debbcc5 | ||
|
|
a138b92b1b | ||
|
|
28619f1786 | ||
|
|
e8f30b708b | ||
|
|
39bc7ed397 | ||
|
|
59852e252b | ||
|
|
51764cc933 | ||
|
|
cb754604f1 |
@@ -133,6 +133,7 @@ packages/app-desktop/gui/ClipperConfigScreen.js
|
||||
packages/app-desktop/gui/ConfigScreen/ButtonBar.js
|
||||
packages/app-desktop/gui/ConfigScreen/ConfigScreen.js
|
||||
packages/app-desktop/gui/ConfigScreen/Sidebar.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/ToggleAdvancedSettingsButton.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/SearchPlugins.js
|
||||
@@ -259,6 +260,7 @@ packages/app-desktop/gui/NoteEditor/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useDropHandler.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useEffectiveNoteId.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useFolder.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useFormNote.test.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useFormNote.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.js
|
||||
@@ -368,6 +370,7 @@ packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js
|
||||
packages/app-desktop/tools/notarizeMacApp.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.test.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtilsTestData.js
|
||||
packages/app-desktop/utils/markupLanguageUtils.js
|
||||
packages/app-mobile/PluginAssetsLoader.js
|
||||
packages/app-mobile/components/ActionButton.js
|
||||
@@ -408,6 +411,7 @@ packages/app-mobile/components/NoteEditor/MarkdownToolbar/Toolbar.js
|
||||
packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToolbarButton.js
|
||||
packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToolbarOverflowRows.js
|
||||
packages/app-mobile/components/NoteEditor/MarkdownToolbar/types.js
|
||||
packages/app-mobile/components/NoteEditor/NoteEditor.test.js
|
||||
packages/app-mobile/components/NoteEditor/NoteEditor.js
|
||||
packages/app-mobile/components/NoteEditor/SearchPanel.js
|
||||
packages/app-mobile/components/NoteEditor/SelectionFormatting.js
|
||||
@@ -418,6 +422,7 @@ packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.js
|
||||
packages/app-mobile/components/ProfileSwitcher/useProfileConfig.js
|
||||
packages/app-mobile/components/ScreenHeader.js
|
||||
packages/app-mobile/components/SelectDateTimeDialog.js
|
||||
packages/app-mobile/components/SideMenu.js
|
||||
packages/app-mobile/components/TextInput.js
|
||||
packages/app-mobile/components/app-nav.js
|
||||
packages/app-mobile/components/biometrics/BiometricPopup.js
|
||||
@@ -514,6 +519,8 @@ packages/lib/commands/index.js
|
||||
packages/lib/commands/openMasterPasswordDialog.js
|
||||
packages/lib/commands/synchronize.js
|
||||
packages/lib/components/EncryptionConfigScreen/utils.js
|
||||
packages/lib/components/shared/config/shouldShowMissingPasswordWarning.test.js
|
||||
packages/lib/components/shared/config/shouldShowMissingPasswordWarning.js
|
||||
packages/lib/components/shared/note-screen-shared.js
|
||||
packages/lib/components/shared/reduxSharedMiddleware.js
|
||||
packages/lib/database-driver-better-sqlite.js
|
||||
@@ -541,6 +548,7 @@ packages/lib/htmlUtils2.test.js
|
||||
packages/lib/import-enex-md-gen.test.js
|
||||
packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex.js
|
||||
packages/lib/initLib.js
|
||||
packages/lib/locale.test.js
|
||||
packages/lib/locale.js
|
||||
packages/lib/markdownUtils.test.js
|
||||
|
||||
15
.github/scripts/run_ci.sh
vendored
15
.github/scripts/run_ci.sh
vendored
@@ -171,6 +171,21 @@ if [ "$IS_PULL_REQUEST" == "1" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Check that the website still builds
|
||||
# =============================================================================
|
||||
|
||||
if [ "$IS_PULL_REQUEST" == "1" ] || [ "$IS_DEV_BRANCH" = "1" ]; then
|
||||
echo "Step: Check that the website still builds..."
|
||||
|
||||
mkdir -p ../joplin-website/docs
|
||||
SKIP_SPONSOR_PROCESSING=1 yarn run buildWebsite
|
||||
testResult=$?
|
||||
if [ $testResult -ne 0 ]; then
|
||||
exit $testResult
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Find out if we should run the build or not. Electron-builder gets stuck when
|
||||
# building PRs so we disable it in this case. The Linux build should provide
|
||||
|
||||
5
.github/workflows/build-android.yml
vendored
5
.github/workflows/build-android.yml
vendored
@@ -25,17 +25,18 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update || true
|
||||
sudo apt-get install -y libsecret-1-dev
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install Yarn
|
||||
run: |
|
||||
corepack enable
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install
|
||||
run: yarn install
|
||||
|
||||
|
||||
1
.github/workflows/build-macos-m1.yml
vendored
1
.github/workflows/build-macos-m1.yml
vendored
@@ -26,6 +26,7 @@ jobs:
|
||||
# We need to pin the version to 18.15, because 18.16+ fails with this error:
|
||||
# https://github.com/facebook/react-native/issues/36440
|
||||
node-version: '18.15.0'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install Yarn
|
||||
run: |
|
||||
|
||||
2
.github/workflows/github-actions-main.yml
vendored
2
.github/workflows/github-actions-main.yml
vendored
@@ -75,6 +75,7 @@ jobs:
|
||||
# We need to pin the version to 18.15, because 18.16+ fails with this error:
|
||||
# https://github.com/facebook/react-native/issues/36440
|
||||
node-version: '18.15.0'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install Yarn
|
||||
run: |
|
||||
@@ -160,6 +161,7 @@ jobs:
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install Yarn
|
||||
run: |
|
||||
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -50,6 +50,7 @@ packages/tools/github_oauth_token.txt
|
||||
lerna-debug.log
|
||||
.env
|
||||
docs/**/*.mustache
|
||||
.idea
|
||||
|
||||
# Yarn stuff
|
||||
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
|
||||
@@ -118,6 +119,7 @@ packages/app-desktop/gui/ClipperConfigScreen.js
|
||||
packages/app-desktop/gui/ConfigScreen/ButtonBar.js
|
||||
packages/app-desktop/gui/ConfigScreen/ConfigScreen.js
|
||||
packages/app-desktop/gui/ConfigScreen/Sidebar.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/ToggleAdvancedSettingsButton.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/SearchPlugins.js
|
||||
@@ -244,6 +246,7 @@ packages/app-desktop/gui/NoteEditor/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useDropHandler.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useEffectiveNoteId.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useFolder.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useFormNote.test.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useFormNote.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.js
|
||||
@@ -353,6 +356,7 @@ packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js
|
||||
packages/app-desktop/tools/notarizeMacApp.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.test.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtilsTestData.js
|
||||
packages/app-desktop/utils/markupLanguageUtils.js
|
||||
packages/app-mobile/PluginAssetsLoader.js
|
||||
packages/app-mobile/components/ActionButton.js
|
||||
@@ -393,6 +397,7 @@ packages/app-mobile/components/NoteEditor/MarkdownToolbar/Toolbar.js
|
||||
packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToolbarButton.js
|
||||
packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToolbarOverflowRows.js
|
||||
packages/app-mobile/components/NoteEditor/MarkdownToolbar/types.js
|
||||
packages/app-mobile/components/NoteEditor/NoteEditor.test.js
|
||||
packages/app-mobile/components/NoteEditor/NoteEditor.js
|
||||
packages/app-mobile/components/NoteEditor/SearchPanel.js
|
||||
packages/app-mobile/components/NoteEditor/SelectionFormatting.js
|
||||
@@ -403,6 +408,7 @@ packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.js
|
||||
packages/app-mobile/components/ProfileSwitcher/useProfileConfig.js
|
||||
packages/app-mobile/components/ScreenHeader.js
|
||||
packages/app-mobile/components/SelectDateTimeDialog.js
|
||||
packages/app-mobile/components/SideMenu.js
|
||||
packages/app-mobile/components/TextInput.js
|
||||
packages/app-mobile/components/app-nav.js
|
||||
packages/app-mobile/components/biometrics/BiometricPopup.js
|
||||
@@ -499,6 +505,8 @@ packages/lib/commands/index.js
|
||||
packages/lib/commands/openMasterPasswordDialog.js
|
||||
packages/lib/commands/synchronize.js
|
||||
packages/lib/components/EncryptionConfigScreen/utils.js
|
||||
packages/lib/components/shared/config/shouldShowMissingPasswordWarning.test.js
|
||||
packages/lib/components/shared/config/shouldShowMissingPasswordWarning.js
|
||||
packages/lib/components/shared/note-screen-shared.js
|
||||
packages/lib/components/shared/reduxSharedMiddleware.js
|
||||
packages/lib/database-driver-better-sqlite.js
|
||||
@@ -526,6 +534,7 @@ packages/lib/htmlUtils2.test.js
|
||||
packages/lib/import-enex-md-gen.test.js
|
||||
packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex.js
|
||||
packages/lib/initLib.js
|
||||
packages/lib/locale.test.js
|
||||
packages/lib/locale.js
|
||||
packages/lib/markdownUtils.test.js
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
diff --git a/android/src/main/java/com/swmansion/reanimated/NodesManager.java b/android/src/main/java/com/swmansion/reanimated/NodesManager.java
|
||||
index e974f8eb827a35be4d7e5fa9b096af9387c595dd..bc9e5ff566c9484274e8eacefc88327a5ff30def 100644
|
||||
--- a/android/src/main/java/com/swmansion/reanimated/NodesManager.java
|
||||
+++ b/android/src/main/java/com/swmansion/reanimated/NodesManager.java
|
||||
@@ -34,7 +34,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
-import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
+import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -80,7 +80,12 @@ public class NodesManager implements EventDispatcherListener {
|
||||
private ReactApplicationContext mReactApplicationContext;
|
||||
private RCTEventEmitter mCustomEventHandler;
|
||||
private List<OnAnimationFrame> mFrameCallbacks = new ArrayList<>();
|
||||
- private ConcurrentLinkedQueue<CopiedEvent> mEventQueue = new ConcurrentLinkedQueue<>();
|
||||
+
|
||||
+ // Patch: On some versions of Android, ConcurrentLinkedQueue is known to
|
||||
+ // drop items. LinkedBlockingQueue is a potentially-slower alternative that
|
||||
+ // should not drop items.
|
||||
+ // See https://github.com/laurent22/joplin/issues/8425
|
||||
+ private LinkedBlockingQueue<CopiedEvent> mEventQueue = new LinkedBlockingQueue<>();
|
||||
public double currentFrameTimeMs;
|
||||
public Set<String> uiProps = Collections.emptySet();
|
||||
public Set<String> nativeProps = Collections.emptySet();
|
||||
BIN
Assets/Aide.png
Normal file
BIN
Assets/Aide.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -112,7 +112,7 @@
|
||||
}).then(async function(result) {
|
||||
if (!result.ok) {
|
||||
console.error('Could not create Stripe checkout session', await result.text());
|
||||
alert('The checkout session could not be created. Please contact support@joplincloud.com for support.');
|
||||
alert('The checkout session could not be created. Please contact us on the forum for support.');
|
||||
} else {
|
||||
return result.json();
|
||||
}
|
||||
|
||||
84
README.md
84
README.md
@@ -75,11 +75,10 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
| | | | |
|
||||
| :---: | :---: | :---: | :---: |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/215668?s=96&v=4"/></br>[avanderberg](https://github.com/avanderberg) | <img width="50" src="https://avatars2.githubusercontent.com/u/67130?s=96&v=4"/></br>[chr15m](https://github.com/chr15m) | <img width="50" src="https://avatars2.githubusercontent.com/u/2793530?s=96&v=4"/></br>[CyberXZT](https://github.com/CyberXZT) | <img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br>[dbrandonjohnson](https://github.com/dbrandonjohnson) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/14873877?s=96&v=4"/></br>[dchecks](https://github.com/dchecks) | <img width="50" src="https://avatars2.githubusercontent.com/u/56287?s=96&v=4"/></br>[fats](https://github.com/fats) | <img width="50" src="https://avatars2.githubusercontent.com/u/49439044?s=96&v=4"/></br>[fourstepper](https://github.com/fourstepper) | <img width="50" src="https://avatars2.githubusercontent.com/u/64712218?s=96&v=4"/></br>[Hegghammer](https://github.com/Hegghammer) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/3266447?s=96&v=4"/></br>[iamwillbar](https://github.com/iamwillbar) | <img width="50" src="https://avatars2.githubusercontent.com/u/1310474?s=96&v=4"/></br>[jknowles](https://github.com/jknowles) | <img width="50" src="https://avatars2.githubusercontent.com/u/11947658?s=96&v=4"/></br>[KentBrockman](https://github.com/KentBrockman) | <img width="50" src="https://avatars2.githubusercontent.com/u/5588131?s=96&v=4"/></br>[kianenigma](https://github.com/kianenigma) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/24908652?s=96&v=4"/></br>[konishi-t](https://github.com/konishi-t) | <img width="50" src="https://avatars2.githubusercontent.com/u/42319182?s=96&v=4"/></br>[marcdw1289](https://github.com/marcdw1289) | <img width="50" src="https://avatars2.githubusercontent.com/u/126279083?s=96&v=4"/></br>[matmoly](https://github.com/matmoly) | <img width="50" src="https://avatars2.githubusercontent.com/u/1788010?s=96&v=4"/></br>[maxtruxa](https://github.com/maxtruxa) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/29300939?s=96&v=4"/></br>[mcejp](https://github.com/mcejp) | <img width="50" src="https://avatars2.githubusercontent.com/u/31054972?s=96&v=4"/></br>[saarantras](https://github.com/saarantras) | <img width="50" src="https://avatars2.githubusercontent.com/u/327998?s=96&v=4"/></br>[sif](https://github.com/sif) | <img width="50" src="https://avatars2.githubusercontent.com/u/765564?s=96&v=4"/></br>[taskcruncher](https://github.com/taskcruncher) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/333944?s=96&v=4"/></br>[tateisu](https://github.com/tateisu) | | | |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/14873877?s=96&v=4"/></br>[dchecks](https://github.com/dchecks) | <img width="50" src="https://avatars2.githubusercontent.com/u/56287?s=96&v=4"/></br>[fats](https://github.com/fats) | <img width="50" src="https://avatars2.githubusercontent.com/u/8030470?s=96&v=4"/></br>[Galliver7](https://github.com/Galliver7) | <img width="50" src="https://avatars2.githubusercontent.com/u/64712218?s=96&v=4"/></br>[Hegghammer](https://github.com/Hegghammer) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/1310474?s=96&v=4"/></br>[jknowles](https://github.com/jknowles) | <img width="50" src="https://avatars2.githubusercontent.com/u/11947658?s=96&v=4"/></br>[KentBrockman](https://github.com/KentBrockman) | <img width="50" src="https://avatars2.githubusercontent.com/u/24908652?s=96&v=4"/></br>[konishi-t](https://github.com/konishi-t) | <img width="50" src="https://avatars2.githubusercontent.com/u/42319182?s=96&v=4"/></br>[marcdw1289](https://github.com/marcdw1289) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/126279083?s=96&v=4"/></br>[matmoly](https://github.com/matmoly) | <img width="50" src="https://avatars2.githubusercontent.com/u/1788010?s=96&v=4"/></br>[maxtruxa](https://github.com/maxtruxa) | <img width="50" src="https://avatars2.githubusercontent.com/u/31054972?s=96&v=4"/></br>[saarantras](https://github.com/saarantras) | <img width="50" src="https://avatars2.githubusercontent.com/u/327998?s=96&v=4"/></br>[sif](https://github.com/sif) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/765564?s=96&v=4"/></br>[taskcruncher](https://github.com/taskcruncher) | <img width="50" src="https://avatars2.githubusercontent.com/u/333944?s=96&v=4"/></br>[tateisu](https://github.com/tateisu) | | |
|
||||
<!-- SPONSORS-GITHUB -->
|
||||
|
||||
<!-- TOC -->
|
||||
@@ -159,6 +158,7 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
- [Guiding principles](https://github.com/laurent22/joplin/blob/dev/readme/principles.md)
|
||||
- [Stats](https://github.com/laurent22/joplin/blob/dev/readme/stats.md)
|
||||
- [Brand guidelines](https://joplinapp.org/brand)
|
||||
- [Release cycle](https://github.com/laurent22/joplin/blob/dev/readme/release_cycle.md)
|
||||
- [Donate](https://github.com/laurent22/joplin/blob/dev/readme/donate.md)
|
||||
<!-- TOC -->
|
||||
|
||||
@@ -232,9 +232,9 @@ Joplin is also capable of exporting to a number of other formats including HTML
|
||||
|
||||
# Synchronisation
|
||||
|
||||
One of the goals of Joplin is to avoid being tied to any particular company or service, whether it is Evernote, Google or Microsoft. As such the synchronisation is designed without any hard dependency to any particular service. Most of the synchronisation process is done at an abstract level and access to external services, such as Nextcloud or Dropbox, is done via lightweight drivers. It is easy to support new services by creating simple drivers that provide a filesystem-like interface, i.e. the ability to read, write, delete and list items. It is also simple to switch from one service to another or to even sync to multiple services at once. Each note, notebook, tags, as well as the relation between items is transmitted as plain text files during synchronisation, which means the data can also be moved to a different application, can be easily backed up, inspected, etc.
|
||||
One of the goals of Joplin is to avoid being tied to any particular company or service, whether it is Evernote, Google or Microsoft. As such the synchronisation is designed without any hard dependency to any particular service. Most of the synchronisation process is done at an abstract level and access to external services, such as Nextcloud or Dropbox, is done via lightweight drivers. It is easy to support new services by creating simple drivers that provide a filesystem-like interface, i.e. the ability to read, write, delete and list items. It is also simple to switch from one service to another.
|
||||
|
||||
Currently, synchronisation is possible with Nextcloud, WebDAV, Dropbox, OneDrive or the local filesystem. To enable synchronisation please follow the instructions below. After that, the application will synchronise in the background whenever it is running, or you can click on "Synchronise" to start a synchronisation manually. Joplin will background sync automatically after any content change is made on the local application.
|
||||
Currently, synchronisation is possible with Joplin Cloud, Nextcloud, S3, WebDAV, Dropbox, OneDrive or the local filesystem. To enable synchronisation please follow the instructions below. After that, the application will synchronise in the background whenever it is running, or you can click on "Synchronise" to start a synchronisation manually. Joplin will background sync automatically after any content change is made on the local application.
|
||||
|
||||
If the **terminal client** has been installed, it is possible to also synchronise outside of the user interface by typing `joplin sync` from the terminal. This can be used to setup a cron script to synchronise at a regular interval. For example, this would do it every 30 minutes:
|
||||
|
||||
@@ -537,47 +537,47 @@ Current translations:
|
||||
<!-- LOCALE-TABLE-AUTO-GENERATED -->
|
||||
| Language | Po File | Last translator | Percent done
|
||||
---|---|---|---|---
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/arableague.png" width="16px"/> | Arabic | [ar](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ar.po) | [Whaell O](mailto:Whaell@protonmail.com) | 79%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/arableague.png" width="16px"/> | Arabic | [ar](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ar.po) | [Whaell O](mailto:Whaell@protonmail.com) | 77%
|
||||
<img src="https://joplinapp.org/images/flags/es/basque_country.png" width="16px"/> | Basque | [eu](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/eu.po) | juan.abasolo@ehu.eus | 22%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ba.png" width="16px"/> | Bosnian (Bosna i Hercegovina) | [bs_BA](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/bs_BA.po) | [Derviš T.](mailto:dervis.t@pm.me) | 57%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/bg.png" width="16px"/> | Bulgarian (България) | [bg_BG](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/bg_BG.po) | | 45%
|
||||
<img src="https://joplinapp.org/images/flags/es/catalonia.png" width="16px"/> | Catalan | [ca](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ca.po) | [Xavi Ivars](mailto:xavi.ivars@gmail.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/hr.png" width="16px"/> | Croatian (Hrvatska) | [hr_HR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hr_HR.po) | [Milo Ivir](mailto:mail@milotype.de) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/cz.png" width="16px"/> | Czech (Česká republika) | [cs_CZ](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/cs_CZ.po) | Fejby | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/dk.png" width="16px"/> | Dansk (Danmark) | [da_DK](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/da_DK.po) | ERYpTION | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/de.png" width="16px"/> | Deutsch (Deutschland) | [de_DE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/de_DE.po) | [MrKanister](mailto:pueblos_spatulas@aleeas.com) | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ee.png" width="16px"/> | Eesti Keel (Eesti) | [et_EE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/et_EE.po) | | 44%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ba.png" width="16px"/> | Bosnian (Bosna i Hercegovina) | [bs_BA](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/bs_BA.po) | [Derviš T.](mailto:dervis.t@pm.me) | 56%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/bg.png" width="16px"/> | Bulgarian (България) | [bg_BG](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/bg_BG.po) | | 44%
|
||||
<img src="https://joplinapp.org/images/flags/es/catalonia.png" width="16px"/> | Catalan | [ca](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ca.po) | [Xavi Ivars](mailto:xavi.ivars@gmail.com) | 86%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/hr.png" width="16px"/> | Croatian (Hrvatska) | [hr_HR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hr_HR.po) | [Milo Ivir](mailto:mail@milotype.de) | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/cz.png" width="16px"/> | Czech (Česká republika) | [cs_CZ](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/cs_CZ.po) | Fejby | 96%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/dk.png" width="16px"/> | Dansk (Danmark) | [da_DK](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/da_DK.po) | ERYpTION | 96%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/de.png" width="16px"/> | Deutsch (Deutschland) | [de_DE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/de_DE.po) | [Mr-Kanister](mailto:viger_gtrc@simplelogin.com) | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ee.png" width="16px"/> | Eesti Keel (Eesti) | [et_EE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/et_EE.po) | | 43%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/gb.png" width="16px"/> | English (United Kingdom) | [en_GB](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/en_GB.po) | | 100%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/us.png" width="16px"/> | English (United States of America) | [en_US](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/en_US.po) | | 100%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/es.png" width="16px"/> | Español (España) | [es_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/es_ES.po) | [Francisco Villaverde](mailto:teko.gr@gmail.com) | 97%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/es.png" width="16px"/> | Español (España) | [es_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/es_ES.po) | [Francisco Villaverde](mailto:teko.gr@gmail.com) | 95%
|
||||
<img src="https://joplinapp.org/images/flags/esperanto.png" width="16px"/> | Esperanto | [eo](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/eo.po) | Marton Paulo | 25%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/fi.png" width="16px"/> | Finnish (Suomi) | [fi_FI](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fi_FI.po) | mrkaato0 | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/fi.png" width="16px"/> | Finnish (Suomi) | [fi_FI](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fi_FI.po) | mrkaato0 | 96%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/fr.png" width="16px"/> | Français (France) | [fr_FR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fr_FR.po) | Laurent Cozic | 100%
|
||||
<img src="https://joplinapp.org/images/flags/es/galicia.png" width="16px"/> | Galician (España) | [gl_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/gl_ES.po) | [Marcos Lans](mailto:marcoslansgarza@gmail.com) | 29%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/id.png" width="16px"/> | Indonesian (Indonesia) | [id_ID](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/id_ID.po) | [Wisnu Adi Santoso](mailto:waditos@gmail.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/it.png" width="16px"/> | Italiano (Italia) | [it_IT](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/it_IT.po) | [Manuel Tassi](mailto:mannivuwiki@gmail.com) | 80%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/hu.png" width="16px"/> | Magyar (Magyarország) | [hu_HU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hu_HU.po) | [Magyari Balázs](mailto:balmag@gmail.com) | 77%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/be.png" width="16px"/> | Nederlands (België, Belgique, Belgien) | [nl_BE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_BE.po) | | 78%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/nl.png" width="16px"/> | Nederlands (Nederland) | [nl_NL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_NL.po) | [MHolkamp](mailto:mholkamp@users.noreply.github.com) | 87%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/no.png" width="16px"/> | Norwegian (Norge, Noreg) | [nb_NO](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nb_NO.po) | [Mats Estensen](mailto:code@mxe.no) | 87%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ir.png" width="16px"/> | Persian | [fa](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fa.po) | [Kourosh Firoozbakht](mailto:kourox@protonmail.com) | 54%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/pl.png" width="16px"/> | Polski (Polska) | [pl_PL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pl_PL.po) | [X3NO](mailto:X3NO@disroot.org) | 89%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/br.png" width="16px"/> | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pt_BR.po) | [Douglas Leão](mailto:djlsplays@gmail.com) | 87%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/pt.png" width="16px"/> | Português (Portugal) | [pt_PT](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pt_PT.po) | [Diogo Caveiro](mailto:dcaveiro@yahoo.com) | 72%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ro.png" width="16px"/> | Română | [ro](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ro.po) | [Cristi Duluta](mailto:cristi.duluta@gmail.com) | 50%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/si.png" width="16px"/> | Slovenian (Slovenija) | [sl_SI](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sl_SI.po) | [Martin Korelič](mailto:martin.korelic@protonmail.com) | 79%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/se.png" width="16px"/> | Svenska | [sv](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sv.po) | [Jonatan Nyberg](mailto:jonatan@autistici.org) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/th.png" width="16px"/> | Thai (ประเทศไทย) | [th_TH](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/th_TH.po) | | 36%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/vn.png" width="16px"/> | Tiếng Việt | [vi](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/vi.po) | | 77%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/tr.png" width="16px"/> | Türkçe (Türkiye) | [tr_TR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/tr_TR.po) | [Arda Kılıçdağı](mailto:arda@kilicdagi.com) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ua.png" width="16px"/> | Ukrainian (Україна) | [uk_UA](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/uk_UA.po) | [Vyacheslav Andreykiv](mailto:vandreykiv@gmail.com) | 71%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/gr.png" width="16px"/> | Ελληνικά (Ελλάδα) | [el_GR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/el_GR.po) | [Harris Arvanitis](mailto:xaris@tuta.io) | 87%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ru.png" width="16px"/> | Русский (Россия) | [ru_RU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ru_RU.po) | [Dmitriy K](mailto:dmitry@atsip.ru) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/rs.png" width="16px"/> | српски језик (Србија) | [sr_RS](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sr_RS.po) | | 64%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/cn.png" width="16px"/> | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_CN.po) | [wh201906](mailto:wh201906@yandex.com) | 96%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/tw.png" width="16px"/> | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_TW.po) | [Kevin Hsu](mailto:kevin.hsu.hws@gmail.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/es/galicia.png" width="16px"/> | Galician (España) | [gl_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/gl_ES.po) | [Marcos Lans](mailto:marcoslansgarza@gmail.com) | 28%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/id.png" width="16px"/> | Indonesian (Indonesia) | [id_ID](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/id_ID.po) | [Wisnu Adi Santoso](mailto:waditos@gmail.com) | 86%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/it.png" width="16px"/> | Italiano (Italia) | [it_IT](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/it_IT.po) | [Manuel Tassi](mailto:mannivuwiki@gmail.com) | 78%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/hu.png" width="16px"/> | Magyar (Magyarország) | [hu_HU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hu_HU.po) | [Magyari Balázs](mailto:balmag@gmail.com) | 75%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/be.png" width="16px"/> | Nederlands (België, Belgique, Belgien) | [nl_BE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_BE.po) | | 76%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/nl.png" width="16px"/> | Nederlands (Nederland) | [nl_NL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_NL.po) | [MHolkamp](mailto:mholkamp@users.noreply.github.com) | 86%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/no.png" width="16px"/> | Norwegian (Norge, Noreg) | [nb_NO](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nb_NO.po) | [Mats Estensen](mailto:code@mxe.no) | 85%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ir.png" width="16px"/> | Persian | [fa](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fa.po) | [Kourosh Firoozbakht](mailto:kourox@protonmail.com) | 53%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/pl.png" width="16px"/> | Polski (Polska) | [pl_PL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pl_PL.po) | [X3NO](mailto:X3NO@disroot.org) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/br.png" width="16px"/> | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pt_BR.po) | [Douglas Leão](mailto:djlsplays@gmail.com) | 85%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/pt.png" width="16px"/> | Português (Portugal) | [pt_PT](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pt_PT.po) | [Diogo Caveiro](mailto:dcaveiro@yahoo.com) | 70%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ro.png" width="16px"/> | Română | [ro](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ro.po) | [Cristi Duluta](mailto:cristi.duluta@gmail.com) | 49%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/si.png" width="16px"/> | Slovenian (Slovenija) | [sl_SI](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sl_SI.po) | [Martin Korelič](mailto:martin.korelic@protonmail.com) | 78%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/se.png" width="16px"/> | Svenska | [sv](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sv.po) | [Jonatan Nyberg](mailto:jonatan@autistici.org) | 97%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/th.png" width="16px"/> | Thai (ประเทศไทย) | [th_TH](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/th_TH.po) | | 35%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/vn.png" width="16px"/> | Tiếng Việt | [vi](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/vi.po) | | 75%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/tr.png" width="16px"/> | Türkçe (Türkiye) | [tr_TR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/tr_TR.po) | [Arda Kılıçdağı](mailto:arda@kilicdagi.com) | 97%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ua.png" width="16px"/> | Ukrainian (Україна) | [uk_UA](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/uk_UA.po) | [Vyacheslav Andreykiv](mailto:vandreykiv@gmail.com) | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/gr.png" width="16px"/> | Ελληνικά (Ελλάδα) | [el_GR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/el_GR.po) | [Harris Arvanitis](mailto:xaris@tuta.io) | 97%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ru.png" width="16px"/> | Русский (Россия) | [ru_RU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ru_RU.po) | [Dmitriy K](mailto:dmitry@atsip.ru) | 97%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/rs.png" width="16px"/> | српски језик (Србија) | [sr_RS](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sr_RS.po) | | 63%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/cn.png" width="16px"/> | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_CN.po) | [qx100](mailto:ztymaxwell@gmail.com) | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/tw.png" width="16px"/> | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_TW.po) | [Kevin Hsu](mailto:kevin.hsu.hws@gmail.com) | 86%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/jp.png" width="16px"/> | 日本語 (日本) | [ja_JP](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ja_JP.po) | [genneko](mailto:genneko217@gmail.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/kr.png" width="16px"/> | 한국어 | [ko](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ko.po) | [Ji-Hyeon Gim](mailto:potatogim@potatogim.net) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/kr.png" width="16px"/> | 한국어 | [ko](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ko.po) | [Ji-Hyeon Gim](mailto:potatogim@potatogim.net) | 86%
|
||||
<!-- LOCALE-TABLE-AUTO-GENERATED -->
|
||||
|
||||
# Contributors
|
||||
|
||||
22
package.json
22
package.json
@@ -64,27 +64,27 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@joplin/utils": "~2.11",
|
||||
"@joplin/utils": "~2.12",
|
||||
"@seiyab/eslint-plugin-react-hooks": "4.5.1-beta.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.0",
|
||||
"@typescript-eslint/parser": "5.59.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.60.0",
|
||||
"@typescript-eslint/parser": "5.60.0",
|
||||
"cspell": "5.21.2",
|
||||
"eslint": "8.39.0",
|
||||
"eslint-interactive": "10.7.0",
|
||||
"eslint": "8.43.0",
|
||||
"eslint-interactive": "10.8.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-jest": "27.2.1",
|
||||
"eslint-plugin-jest": "27.2.2",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-react": "7.32.2",
|
||||
"execa": "5.1.1",
|
||||
"fs-extra": "11.1.1",
|
||||
"glob": "10.2.7",
|
||||
"glob": "10.3.3",
|
||||
"gulp": "4.0.2",
|
||||
"husky": "3.1.0",
|
||||
"lerna": "3.22.1",
|
||||
"lint-staged": "13.2.3",
|
||||
"madge": "6.1.0",
|
||||
"npm-package-json-lint": "6.4.0",
|
||||
"typescript": "5.0.2"
|
||||
"typescript": "5.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/fs-extra": "11.0.1",
|
||||
@@ -93,14 +93,14 @@
|
||||
"node-gyp": "9.4.0",
|
||||
"nodemon": "2.0.22"
|
||||
},
|
||||
"packageManager": "yarn@3.5.0",
|
||||
"packageManager": "yarn@3.6.0",
|
||||
"resolutions": {
|
||||
"react-native-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch",
|
||||
"react-native-vosk@0.1.12": "patch:react-native-vosk@npm%3A0.1.12#./.yarn/patches/react-native-vosk-npm-0.1.12-76b1caaae8.patch",
|
||||
"eslint@8.39.0": "patch:eslint@npm%3A8.39.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
|
||||
"eslint@8.43.0": "patch:eslint@npm%3A8.39.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
|
||||
"eslint@^8.13.0": "patch:eslint@npm%3A8.39.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
|
||||
"app-builder-lib@24.4.0": "patch:app-builder-lib@npm%3A24.4.0#./.yarn/patches/app-builder-lib-npm-24.4.0-05322ff057.patch",
|
||||
"react-native@0.71.10": "patch:react-native@npm%3A0.71.10#./.yarn/patches/react-native-animation-fix/react-native-npm-0.71.10-f9c32562d8.patch",
|
||||
"react-native-reanimated@3.3.0": "patch:react-native-reanimated@npm%3A3.3.0#./.yarn/patches/react-native-animation-fix/react-native-reanimated-npm-3.3.0-fb4272741c.patch"
|
||||
"react-native@0.71.10": "patch:react-native@npm%3A0.71.10#./.yarn/patches/react-native-animation-fix/react-native-npm-0.71.10-f9c32562d8.patch"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,6 +452,8 @@ class Application extends BaseApplication {
|
||||
type: 'FOLDER_SELECT',
|
||||
id: Setting.value('activeFolderId'),
|
||||
});
|
||||
|
||||
this.startRotatingLogMaintenance(Setting.value('profileDir'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ const { FileApiDriverLocal } = require('@joplin/lib/file-api-driver-local');
|
||||
const EncryptionService = require('@joplin/lib/services/e2ee/EncryptionService').default;
|
||||
const envFromArgs = require('@joplin/lib/envFromArgs');
|
||||
const nodeSqlite = require('sqlite3');
|
||||
const initLib = require('@joplin/lib/initLib').default;
|
||||
|
||||
const env = envFromArgs(process.argv);
|
||||
|
||||
@@ -67,6 +68,10 @@ function appVersion() {
|
||||
|
||||
shimInit({ sharp, keytar, appVersion, nodeSqlite });
|
||||
|
||||
const logger = new Logger();
|
||||
Logger.initializeGlobalLogger(logger);
|
||||
initLib(logger);
|
||||
|
||||
const application = app();
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"proper-lockfile": "4.1.2",
|
||||
"read-chunk": "2.1.0",
|
||||
"server-destroy": "1.0.1",
|
||||
"sharp": "0.32.1",
|
||||
"sharp": "0.32.4",
|
||||
"sprintf-js": "1.1.2",
|
||||
"sqlite3": "5.1.6",
|
||||
"string-padding": "1.0.2",
|
||||
@@ -66,18 +66,18 @@
|
||||
"terminal-kit": "3.0.0",
|
||||
"tkwidgets": "0.5.27",
|
||||
"url-parse": "1.5.10",
|
||||
"word-wrap": "1.2.3",
|
||||
"word-wrap": "1.2.5",
|
||||
"yargs-parser": "21.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@joplin/tools": "~2.12",
|
||||
"@types/fs-extra": "11.0.1",
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/node": "18.15.13",
|
||||
"@types/jest": "29.5.3",
|
||||
"@types/node": "18.16.18",
|
||||
"@types/proper-lockfile": "^4.1.2",
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.5.0",
|
||||
"temp": "0.9.4",
|
||||
"typescript": "5.0.2"
|
||||
"typescript": "5.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ export default class ElectronAppWrapper {
|
||||
// so that it can tell us if we can really close the app or not.
|
||||
// Search for "appClose" event for closing logic on renderer side.
|
||||
event.preventDefault();
|
||||
this.win_.webContents.send('appClose');
|
||||
if (this.win_) this.win_.webContents.send('appClose');
|
||||
} else {
|
||||
// If the renderer process has responded, check if we can close or not
|
||||
if (this.rendererProcessQuitReply_.canClose) {
|
||||
|
||||
@@ -566,6 +566,8 @@ class Application extends BaseApplication {
|
||||
|
||||
await SpellCheckerService.instance().initialize(new SpellCheckerServiceDriverNative());
|
||||
|
||||
this.startRotatingLogMaintenance(Setting.value('profileDir'));
|
||||
|
||||
// await populateDatabase(reg.db(), {
|
||||
// clearDatabase: true,
|
||||
// folderCount: 1000,
|
||||
|
||||
@@ -23,8 +23,8 @@ function onCheckEnded() {
|
||||
isCheckingForUpdate_ = false;
|
||||
}
|
||||
|
||||
async function fetchLatestRelease() {
|
||||
const response = await shim.fetch('https://api.github.com/repos/laurent22/joplin/releases');
|
||||
async function fetchLatestReleases() {
|
||||
const response = await shim.fetch('https://objects.joplinusercontent.com/r/releases');
|
||||
|
||||
if (!response.ok) {
|
||||
const responseText = await response.text();
|
||||
@@ -76,8 +76,8 @@ export default async function checkForUpdates(inBackground: boolean, parentWindo
|
||||
logger.info(`Checking with options ${JSON.stringify(options)}`);
|
||||
|
||||
try {
|
||||
const releases = await fetchLatestRelease();
|
||||
const release = extractVersionInfo(releases, process.platform, options);
|
||||
const releases = await fetchLatestReleases();
|
||||
const release = extractVersionInfo(releases, process.platform, process.arch, shim.isPortable(), options);
|
||||
|
||||
logger.info(`Current version: ${packageInfo.version}`);
|
||||
logger.info(`Latest version: ${release.version}`);
|
||||
|
||||
@@ -2,7 +2,6 @@ import CommandService, { CommandRuntime, CommandDeclaration } from '@joplin/lib/
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
import { DesktopCommandContext } from '../services/commands/types';
|
||||
import { enabledCondition } from '../gui/NoteEditor/editorCommandDeclarations';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleExternalEditing',
|
||||
@@ -23,7 +22,7 @@ export const runtime = (): CommandRuntime => {
|
||||
void CommandService.instance().execute('startExternalEditing', noteId);
|
||||
}
|
||||
},
|
||||
enabledCondition: enabledCondition(declaration.name),
|
||||
enabledCondition: 'oneNoteSelected && !noteIsReadOnly && (!modalDialogVisible || gotoAnythingVisible)',
|
||||
mapStateToTitle: (state: any) => {
|
||||
const noteId = stateUtils.selectedNoteId(state);
|
||||
return state.watchedNoteFiles.includes(noteId) ? _('Stop') : '';
|
||||
|
||||
@@ -12,13 +12,17 @@ const { connect } = require('react-redux');
|
||||
const { themeStyle } = require('@joplin/lib/theme');
|
||||
const pathUtils = require('@joplin/lib/path-utils');
|
||||
import SyncTargetRegistry from '@joplin/lib/SyncTargetRegistry';
|
||||
const shared = require('@joplin/lib/components/shared/config-shared.js');
|
||||
const shared = require('@joplin/lib/components/shared/config/config-shared.js');
|
||||
import ClipperConfigScreen from '../ClipperConfigScreen';
|
||||
import restart from '../../services/restart';
|
||||
import PluginService from '@joplin/lib/services/plugins/PluginService';
|
||||
import { getDefaultPluginsInstallState, updateDefaultPluginsInstallState } from '@joplin/lib/services/plugins/defaultPlugins/defaultPluginsUtils';
|
||||
import getDefaultPluginsInfo from '@joplin/lib/services/plugins/defaultPlugins/desktopDefaultPluginsInfo';
|
||||
import JoplinCloudConfigScreen from '../JoplinCloudConfigScreen';
|
||||
import ToggleAdvancedSettingsButton from './controls/ToggleAdvancedSettingsButton';
|
||||
import shouldShowMissingPasswordWarning from '@joplin/lib/components/shared/config/shouldShowMissingPasswordWarning';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import StyledLink from '../style/StyledLink';
|
||||
const { KeymapConfigScreen } = require('../KeymapConfig/KeymapConfigScreen');
|
||||
|
||||
const settingKeyToControl: any = {
|
||||
@@ -180,6 +184,34 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
if (section.name === 'sync') {
|
||||
const syncTargetMd = SyncTargetRegistry.idToMetadata(settings['sync.target']);
|
||||
const statusStyle = { ...theme.textStyle, marginTop: 10 };
|
||||
const warningStyle = { ...theme.textStyle, color: theme.colorWarn };
|
||||
|
||||
// Don't show the missing password warning if the user just changed the sync target (but hasn't
|
||||
// saved yet).
|
||||
const matchesSavedTarget = settings['sync.target'] === this.props.settings['sync.target'];
|
||||
if (matchesSavedTarget && shouldShowMissingPasswordWarning(settings['sync.target'], settings)) {
|
||||
const openMissingPasswordFAQ = () =>
|
||||
bridge().openExternal('https://joplinapp.org/faq#why-did-my-sync-and-encryption-passwords-disappear-after-updating-joplin');
|
||||
|
||||
const macInfoLink = (
|
||||
<StyledLink href="#"
|
||||
onClick={openMissingPasswordFAQ}
|
||||
style={theme.linkStyle}
|
||||
>
|
||||
{_('Help')}
|
||||
</StyledLink>
|
||||
);
|
||||
|
||||
// The FAQ section related to missing passwords is specific to MacOS/ARM -- only show it
|
||||
// in that case.
|
||||
const showMacInfoLink = shim.isMac() && process.arch === 'arm64';
|
||||
|
||||
settingComps.push(
|
||||
<p key='missing-password-warning' style={warningStyle}>
|
||||
{_('Warning: Missing password.')}{' '}{showMacInfoLink ? macInfoLink : null}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
if (syncTargetMd.supportsConfigCheck) {
|
||||
const messages = shared.checkSyncConfigMessages(this);
|
||||
@@ -208,17 +240,11 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
const advancedSettingsSectionStyle = { display: 'none' };
|
||||
|
||||
if (advancedSettingComps.length) {
|
||||
const iconName = this.state.showAdvancedSettings ? 'fa fa-angle-down' : 'fa fa-angle-right';
|
||||
// const advancedSettingsButtonStyle = { ...theme.buttonStyle, marginBottom: 10 };
|
||||
advancedSettingsButton = (
|
||||
<div style={{ marginBottom: 10 }}>
|
||||
<Button
|
||||
level={ButtonLevel.Secondary}
|
||||
onClick={() => shared.advancedSettingsButton_click(this)}
|
||||
iconName={iconName}
|
||||
title={_('Show Advanced Settings')}
|
||||
/>
|
||||
</div>
|
||||
<ToggleAdvancedSettingsButton
|
||||
onClick={() => shared.advancedSettingsButton_click(this)}
|
||||
advancedSettingsVisible={this.state.showAdvancedSettings}
|
||||
/>
|
||||
);
|
||||
advancedSettingsSectionStyle.display = this.state.showAdvancedSettings ? 'block' : 'none';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import Button, { ButtonLevel } from '../../Button/Button';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
interface Props {
|
||||
onClick: ()=> void;
|
||||
advancedSettingsVisible: boolean;
|
||||
}
|
||||
|
||||
const ToggleAdvancedSettingsButton: React.FunctionComponent<Props> = props => {
|
||||
const iconName = props.advancedSettingsVisible ? 'fa fa-angle-down' : 'fa fa-angle-right';
|
||||
return (
|
||||
<div style={{ marginBottom: 10 }}>
|
||||
<Button
|
||||
level={ButtonLevel.Secondary}
|
||||
onClick={props.onClick}
|
||||
iconName={iconName}
|
||||
title={_('Show Advanced Settings')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default ToggleAdvancedSettingsButton;
|
||||
@@ -10,12 +10,13 @@ import { MasterKeyEntity } from '@joplin/lib/services/e2ee/types';
|
||||
import { getEncryptionEnabled, masterKeyEnabled, SyncInfo } from '@joplin/lib/services/synchronizer/syncInfoUtils';
|
||||
import { getDefaultMasterKey, getMasterPasswordStatusMessage, masterPasswordIsValid, toggleAndSetupEncryption } from '@joplin/lib/services/e2ee/utils';
|
||||
import Button, { ButtonLevel } from '../Button/Button';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { AppState } from '../../app.reducer';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import { PublicPrivateKeyPair } from '@joplin/lib/services/e2ee/ppk';
|
||||
import ToggleAdvancedSettingsButton from '../ConfigScreen/controls/ToggleAdvancedSettingsButton';
|
||||
|
||||
interface Props {
|
||||
themeId: any;
|
||||
@@ -83,34 +84,6 @@ const EncryptionConfigScreen = (props: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
const renderReencryptData = () => {
|
||||
if (!shim.isElectron()) return null;
|
||||
if (!props.shouldReencrypt) return null;
|
||||
|
||||
const theme = themeStyle(props.themeId);
|
||||
const buttonLabel = _('Re-encrypt data');
|
||||
|
||||
const intro = props.shouldReencrypt ? _('The default encryption method has been changed to a more secure one and it is recommended that you apply it to your data.') : _('You may use the tool below to re-encrypt your data, for example if you know that some of your notes are encrypted with an obsolete encryption method.');
|
||||
|
||||
let t = `${intro}\n\n${_('In order to do so, your entire data set will have to be encrypted and synchronised, so it is best to run it overnight.\n\nTo start, please follow these instructions:\n\n1. Synchronise all your devices.\n2. Click "%s".\n3. Let it run to completion. While it runs, avoid changing any note on your other devices, to avoid conflicts.\n4. Once sync is done on this device, sync all your other devices and let it run to completion.\n\nImportant: you only need to run this ONCE on one device.', buttonLabel)}`;
|
||||
|
||||
t = t.replace(/\n\n/g, '</p><p>');
|
||||
t = t.replace(/\n/g, '<br>');
|
||||
t = `<p>${t}</p>`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>{_('Re-encryption')}</h2>
|
||||
<p style={theme.textStyle} dangerouslySetInnerHTML={{ __html: t }}></p>
|
||||
<span style={{ marginRight: 10 }}>
|
||||
<button onClick={() => void reencryptData()} style={theme.buttonStyle}>{buttonLabel}</button>
|
||||
</span>
|
||||
|
||||
{ !props.shouldReencrypt ? null : <button onClick={() => dontReencryptData()} style={theme.buttonStyle}>{_('Ignore')}</button> }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderMasterKey = (mk: MasterKeyEntity) => {
|
||||
const theme = themeStyle(props.themeId);
|
||||
|
||||
@@ -121,6 +94,12 @@ const EncryptionConfigScreen = (props: Props) => {
|
||||
borderColor: theme.dividerColor,
|
||||
};
|
||||
|
||||
const missingPasswordCellStyle = {
|
||||
...theme.textStyle,
|
||||
border: '3px solid',
|
||||
borderColor: theme.colorError,
|
||||
};
|
||||
|
||||
const password = inputPasswords[mk.id] ? inputPasswords[mk.id] : '';
|
||||
const isActive = props.activeMasterKeyId === mk.id;
|
||||
const activeIcon = isActive ? '✔' : '';
|
||||
@@ -135,8 +114,15 @@ const EncryptionConfigScreen = (props: Props) => {
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<td style={theme.textStyle}>
|
||||
<input type="password" style={passwordStyle} value={password} onChange={event => onInputPasswordChange(mk, event.target.value)} />{' '}
|
||||
<td style={missingPasswordCellStyle}>
|
||||
<input
|
||||
type="password"
|
||||
placeholder={_('Enter password')}
|
||||
style={passwordStyle}
|
||||
value={password}
|
||||
onChange={event => onInputPasswordChange(mk, event.target.value)}
|
||||
/>
|
||||
{' '}
|
||||
<button style={theme.buttonStyle} onClick={() => onSavePasswordClick(mk, { ...props.passwords, ...inputPasswords })}>
|
||||
{_('Save')}
|
||||
</button>
|
||||
@@ -239,7 +225,6 @@ const EncryptionConfigScreen = (props: Props) => {
|
||||
/>
|
||||
);
|
||||
const needUpgradeSection = renderNeedUpgradeSection();
|
||||
const reencryptDataSection = renderReencryptData();
|
||||
|
||||
return (
|
||||
<div className="section">
|
||||
@@ -254,7 +239,6 @@ const EncryptionConfigScreen = (props: Props) => {
|
||||
{decryptedItemsInfo}
|
||||
{toggleButton}
|
||||
{needUpgradeSection}
|
||||
{props.shouldReencrypt ? reencryptDataSection : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -338,6 +322,56 @@ const EncryptionConfigScreen = (props: Props) => {
|
||||
return nonExistingMasterKeySection;
|
||||
};
|
||||
|
||||
const renderReencryptData = () => {
|
||||
if (!shim.isElectron()) return null;
|
||||
if (!props.encryptionEnabled) return null;
|
||||
|
||||
const theme = themeStyle(props.themeId);
|
||||
const buttonLabel = _('Re-encrypt data');
|
||||
|
||||
const intro = props.shouldReencrypt ? _('The default encryption method has been changed to a more secure one and it is recommended that you apply it to your data.') : _('You may use the tool below to re-encrypt your data, for example if you know that some of your notes are encrypted with an obsolete encryption method.');
|
||||
|
||||
let t = `${intro}\n\n${_('In order to do so, your entire data set will have to be encrypted and synchronised, so it is best to run it overnight.\n\nTo start, please follow these instructions:\n\n1. Synchronise all your devices.\n2. Click "%s".\n3. Let it run to completion. While it runs, avoid changing any note on your other devices, to avoid conflicts.\n4. Once sync is done on this device, sync all your other devices and let it run to completion.\n\nImportant: you only need to run this ONCE on one device.', buttonLabel)}`;
|
||||
|
||||
t = t.replace(/\n\n/g, '</p><p>');
|
||||
t = t.replace(/\n/g, '<br>');
|
||||
t = `<p>${t}</p>`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>{_('Re-encryption')}</h2>
|
||||
<p style={theme.textStyle} dangerouslySetInnerHTML={{ __html: t }}></p>
|
||||
<span style={{ marginRight: 10 }}>
|
||||
<button onClick={() => void reencryptData()} style={theme.buttonStyle}>{buttonLabel}</button>
|
||||
</span>
|
||||
|
||||
{ !props.shouldReencrypt ? null : <button onClick={() => dontReencryptData()} style={theme.buttonStyle}>{_('Ignore')}</button> }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// If the user should re-encrypt, ensure that the section is visible initially.
|
||||
const [showAdvanced, setShowAdvanced] = useState<boolean>(props.shouldReencrypt);
|
||||
const toggleAdvanced = useCallback(() => {
|
||||
setShowAdvanced(!showAdvanced);
|
||||
}, [showAdvanced]);
|
||||
|
||||
const renderAdvancedSection = () => {
|
||||
const reEncryptSection = renderReencryptData();
|
||||
|
||||
if (!reEncryptSection) return null;
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ToggleAdvancedSettingsButton
|
||||
onClick={toggleAdvanced}
|
||||
advancedSettingsVisible={showAdvanced}/>
|
||||
{ showAdvanced ? reEncryptSection : null }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="config-screen-content">
|
||||
{renderDebugSection()}
|
||||
@@ -346,6 +380,7 @@ const EncryptionConfigScreen = (props: Props) => {
|
||||
{renderMasterKeySection(props.masterKeys.filter(mk => masterKeyEnabled(mk)), true)}
|
||||
{renderMasterKeySection(props.masterKeys.filter(mk => !masterKeyEnabled(mk)), false)}
|
||||
{renderNonExistingMasterKeysSection()}
|
||||
{renderAdvancedSection()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ interface State {
|
||||
|
||||
interface Props {
|
||||
message?: string;
|
||||
children: any;
|
||||
}
|
||||
|
||||
export default class ErrorBoundary extends React.Component<Props, State> {
|
||||
|
||||
@@ -20,6 +20,7 @@ import NoteListWrapper from '../NoteListWrapper/NoteListWrapper';
|
||||
import { AppState } from '../../app.reducer';
|
||||
import { saveLayout, loadLayout } from '../ResizableLayout/utils/persist';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import shouldShowMissingPasswordWarning from '@joplin/lib/components/shared/config/shouldShowMissingPasswordWarning';
|
||||
import produce from 'immer';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import bridge from '../../services/bridge';
|
||||
@@ -67,6 +68,7 @@ interface Props {
|
||||
shouldUpgradeSyncTarget: boolean;
|
||||
hasDisabledSyncItems: boolean;
|
||||
hasDisabledEncryptionItems: boolean;
|
||||
hasMissingSyncCredentials: boolean;
|
||||
showMissingMasterKeyMessage: boolean;
|
||||
showNeedUpgradingMasterKeyMessage: boolean;
|
||||
showShouldReencryptMessage: boolean;
|
||||
@@ -561,6 +563,16 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
});
|
||||
};
|
||||
|
||||
const onViewSyncSettingsScreen = () => {
|
||||
this.props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Config',
|
||||
props: {
|
||||
defaultSection: 'sync',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onViewPluginScreen = () => {
|
||||
this.props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
@@ -598,6 +610,12 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
_('Disable safe mode and restart'),
|
||||
onDisableSafeModeAndRestart
|
||||
);
|
||||
} else if (this.props.hasMissingSyncCredentials) {
|
||||
msg = this.renderNotificationMessage(
|
||||
_('The synchronisation password is missing.'),
|
||||
_('Set the password'),
|
||||
onViewSyncSettingsScreen
|
||||
);
|
||||
} else if (this.props.shouldUpgradeSyncTarget) {
|
||||
msg = this.renderNotificationMessage(
|
||||
_('The sync target needs to be upgraded before Joplin can sync. The operation may take a few minutes to complete and the app needs to be restarted. To proceed please click on the link.'),
|
||||
@@ -662,7 +680,7 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
|
||||
public messageBoxVisible(props: Props = null) {
|
||||
if (!props) props = this.props;
|
||||
return props.hasDisabledSyncItems || props.showMissingMasterKeyMessage || props.showNeedUpgradingMasterKeyMessage || props.showShouldReencryptMessage || props.hasDisabledEncryptionItems || this.props.shouldUpgradeSyncTarget || props.isSafeMode || this.showShareInvitationNotification(props) || this.props.needApiAuth || this.props.showInstallTemplatesPlugin;
|
||||
return props.hasDisabledSyncItems || props.showMissingMasterKeyMessage || props.hasMissingSyncCredentials || props.showNeedUpgradingMasterKeyMessage || props.showShouldReencryptMessage || props.hasDisabledEncryptionItems || this.props.shouldUpgradeSyncTarget || props.isSafeMode || this.showShareInvitationNotification(props) || this.props.needApiAuth || this.props.showInstallTemplatesPlugin;
|
||||
}
|
||||
|
||||
public registerCommands() {
|
||||
@@ -875,6 +893,7 @@ const mapStateToProps = (state: AppState) => {
|
||||
showNeedUpgradingMasterKeyMessage: showNeedUpgradingEnabledMasterKeyMessage,
|
||||
showShouldReencryptMessage: state.settings['encryption.shouldReencrypt'] >= Setting.SHOULD_REENCRYPT_YES,
|
||||
shouldUpgradeSyncTarget: state.settings['sync.upgradeState'] === Setting.SYNC_UPGRADE_STATE_SHOULD_DO,
|
||||
hasMissingSyncCredentials: shouldShowMissingPasswordWarning(state.settings['sync.target'], state.settings),
|
||||
pluginsLegacy: state.pluginsLegacy,
|
||||
plugins: state.pluginService.plugins,
|
||||
pluginHtmlContents: state.pluginService.pluginHtmlContents,
|
||||
|
||||
@@ -38,6 +38,7 @@ export const runtime = (): CommandRuntime => {
|
||||
menuItem.click();
|
||||
});
|
||||
}
|
||||
return null;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -99,7 +99,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const addListItem = useCallback((string1, defaultText = '') => {
|
||||
const addListItem = useCallback((string1: string, defaultText = '') => {
|
||||
if (editorRef.current) {
|
||||
if (editorRef.current.somethingSelected()) {
|
||||
editorRef.current.wrapSelectionsByLine(string1);
|
||||
|
||||
@@ -141,7 +141,7 @@ export default function useScrollHandler(editorRef: any, webviewRef: any, onScro
|
||||
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
|
||||
}, []);
|
||||
|
||||
const editor_resize = useCallback((cm) => {
|
||||
const editor_resize = useCallback((cm: any) => {
|
||||
if (isCodeMirrorReady(cm)) {
|
||||
// This handler is called when resized and refreshed.
|
||||
// Only when resized, the scroll position is restored.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import TinyMCE from './NoteBody/TinyMCE/TinyMCE';
|
||||
import CodeMirror from './NoteBody/CodeMirror/CodeMirror';
|
||||
import { connect } from 'react-redux';
|
||||
@@ -40,7 +40,7 @@ import Note from '@joplin/lib/models/Note';
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
const bridge = require('@electron/remote').require('./bridge').default;
|
||||
import NoteRevisionViewer from '../NoteRevisionViewer';
|
||||
import { readFromSettings } from '@joplin/lib/services/share/reducer';
|
||||
import { parseShareCache } from '@joplin/lib/services/share/reducer';
|
||||
import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect';
|
||||
import { ModelType } from '@joplin/lib/BaseModel';
|
||||
import BaseItem from '@joplin/lib/models/BaseItem';
|
||||
@@ -78,6 +78,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
|
||||
const { formNote, setFormNote, isNewNote, resourceInfos } = useFormNote({
|
||||
syncStarted: props.syncStarted,
|
||||
decryptionStarted: props.decryptionStarted,
|
||||
noteId: effectiveNoteId,
|
||||
isProvisional: props.isProvisional,
|
||||
titleInputRef: titleInputRef,
|
||||
@@ -286,11 +287,15 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
// }
|
||||
// }, [props.dispatch]);
|
||||
|
||||
const shareCache = useMemo(() => {
|
||||
return parseShareCache(props.shareCacheSetting);
|
||||
}, [props.shareCacheSetting]);
|
||||
|
||||
useAsyncEffect(async event => {
|
||||
if (!formNote.id) return;
|
||||
|
||||
try {
|
||||
const result = await itemIsReadOnly(BaseItem, ModelType.Note, ItemChange.SOURCE_UNSPECIFIED, formNote.id, props.syncUserId, props.shareCache);
|
||||
const result = await itemIsReadOnly(BaseItem, ModelType.Note, ItemChange.SOURCE_UNSPECIFIED, formNote.id, props.syncUserId, shareCache);
|
||||
if (event.cancelled) return;
|
||||
setIsReadOnly(result);
|
||||
} catch (error) {
|
||||
@@ -301,7 +306,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}, [formNote.id, props.syncUserId, props.shareCache]);
|
||||
}, [formNote.id, props.syncUserId, shareCache]);
|
||||
|
||||
const onBodyWillChange = useCallback((event: any) => {
|
||||
handleProvisionalFlag();
|
||||
@@ -324,7 +329,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
|
||||
const onMessage = useMessageHandler(scrollWhenReady, setScrollWhenReady, editorRef, setLocalSearchResultCount, props.dispatch, formNote);
|
||||
|
||||
const externalEditWatcher_noteChange = useCallback((event) => {
|
||||
const externalEditWatcher_noteChange = useCallback((event: any) => {
|
||||
if (event.id === formNote.id) {
|
||||
const newFormNote = {
|
||||
...formNote,
|
||||
@@ -337,7 +342,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
|
||||
}, [formNote]);
|
||||
|
||||
const onNotePropertyChange = useCallback((event) => {
|
||||
const onNotePropertyChange = useCallback((event: any) => {
|
||||
setFormNote(formNote => {
|
||||
if (formNote.id !== event.note.id) return formNote;
|
||||
|
||||
@@ -629,6 +634,7 @@ const mapStateToProps = (state: AppState) => {
|
||||
isProvisional: state.provisionalNoteIds.includes(noteId),
|
||||
editorNoteStatuses: state.editorNoteStatuses,
|
||||
syncStarted: state.syncStarted,
|
||||
decryptionStarted: state.decryptionWorker?.state !== 'idle',
|
||||
themeId: state.settings.theme,
|
||||
richTextBannerDismissed: state.settings.richTextBannerDismissed,
|
||||
watchedNoteFiles: state.watchedNoteFiles,
|
||||
@@ -656,7 +662,7 @@ const mapStateToProps = (state: AppState) => {
|
||||
isSafeMode: state.settings.isSafeMode,
|
||||
useCustomPdfViewer: false,
|
||||
syncUserId: state.settings['sync.userId'],
|
||||
shareCache: readFromSettings(state),
|
||||
shareCacheSetting: state.settings['sync.shareCache'],
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ export async function commandAttachFileToBody(body: string, filePaths: string[]
|
||||
logger.info(`Attaching ${filePath}`);
|
||||
const newBody = await shim.attachFileToNoteBody(body, filePath, options.position, {
|
||||
createFileURL: options.createFileURL,
|
||||
resizeLargeImages: 'ask',
|
||||
resizeLargeImages: Setting.value('imageResizing'),
|
||||
});
|
||||
|
||||
if (!newBody) {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import AsyncActionQueue from '@joplin/lib/AsyncActionQueue';
|
||||
import { ToolbarButtonInfo } from '@joplin/lib/services/commands/ToolbarButtonUtils';
|
||||
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
|
||||
import { State as ShareState } from '@joplin/lib/services/share/reducer';
|
||||
import { MarkupLanguage } from '@joplin/renderer';
|
||||
import { RenderResult, RenderResultPluginAsset } from '@joplin/renderer/MarkupToHtml';
|
||||
import { MarkupToHtmlOptions } from './useMarkupToHtml';
|
||||
@@ -28,6 +27,7 @@ export interface NoteEditorProps {
|
||||
isProvisional: boolean;
|
||||
editorNoteStatuses: any;
|
||||
syncStarted: boolean;
|
||||
decryptionStarted: boolean;
|
||||
bodyEditor: string;
|
||||
notesParentType: string;
|
||||
selectedNoteTags: any[];
|
||||
@@ -46,7 +46,7 @@ export interface NoteEditorProps {
|
||||
contentMaxWidth: number;
|
||||
isSafeMode: boolean;
|
||||
useCustomPdfViewer: boolean;
|
||||
shareCache: ShareState;
|
||||
shareCacheSetting: string;
|
||||
syncUserId: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import { setupDatabaseAndSynchronizer, switchClient } from '@joplin/lib/testing/test-utils';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import useFormNote, { HookDependencies } from './useFormNote';
|
||||
|
||||
|
||||
describe('useFormNote', () => {
|
||||
beforeEach(async () => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
});
|
||||
|
||||
it('should update note when decryption completes', async () => {
|
||||
const testNote = await Note.save({ title: 'Test Note!' });
|
||||
|
||||
const makeFormNoteProps = (syncStarted: boolean, decryptionStarted: boolean): HookDependencies => {
|
||||
return {
|
||||
syncStarted,
|
||||
decryptionStarted,
|
||||
noteId: testNote.id,
|
||||
isProvisional: false,
|
||||
titleInputRef: null,
|
||||
editorRef: null,
|
||||
onBeforeLoad: ()=>{},
|
||||
onAfterLoad: ()=>{},
|
||||
};
|
||||
};
|
||||
|
||||
const formNote = renderHook(props => useFormNote(props), {
|
||||
initialProps: makeFormNoteProps(true, false),
|
||||
});
|
||||
await formNote.waitFor(() => {
|
||||
expect(formNote.result.current.formNote).toMatchObject({
|
||||
encryption_applied: 0,
|
||||
title: testNote.title,
|
||||
});
|
||||
});
|
||||
|
||||
await Note.save({
|
||||
id: testNote.id,
|
||||
encryption_cipher_text: 'cipher_text',
|
||||
encryption_applied: 1,
|
||||
});
|
||||
|
||||
// Sync starting should cause a re-render
|
||||
formNote.rerender(makeFormNoteProps(false, false));
|
||||
|
||||
await formNote.waitFor(() => {
|
||||
expect(formNote.result.current.formNote).toMatchObject({
|
||||
encryption_applied: 1,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
formNote.rerender(makeFormNoteProps(false, true));
|
||||
|
||||
await Note.save({
|
||||
id: testNote.id,
|
||||
encryption_applied: 0,
|
||||
title: 'Test Note!',
|
||||
});
|
||||
|
||||
// Ending decryption should also cause a re-render
|
||||
formNote.rerender(makeFormNoteProps(false, false));
|
||||
|
||||
await formNote.waitFor(() => {
|
||||
expect(formNote.result.current.formNote).toMatchObject({
|
||||
encryption_applied: 0,
|
||||
title: 'Test Note!',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -18,8 +18,9 @@ export interface OnLoadEvent {
|
||||
formNote: FormNote;
|
||||
}
|
||||
|
||||
interface HookDependencies {
|
||||
export interface HookDependencies {
|
||||
syncStarted: boolean;
|
||||
decryptionStarted: boolean;
|
||||
noteId: string;
|
||||
isProvisional: boolean;
|
||||
titleInputRef: any;
|
||||
@@ -61,14 +62,21 @@ function resourceInfosChanged(a: ResourceInfos, b: ResourceInfos): boolean {
|
||||
}
|
||||
|
||||
export default function useFormNote(dependencies: HookDependencies) {
|
||||
const { syncStarted, noteId, isProvisional, titleInputRef, editorRef, onBeforeLoad, onAfterLoad } = dependencies;
|
||||
const {
|
||||
syncStarted, decryptionStarted, noteId, isProvisional, titleInputRef, editorRef, onBeforeLoad, onAfterLoad,
|
||||
} = dependencies;
|
||||
|
||||
const [formNote, setFormNote] = useState<FormNote>(defaultFormNote());
|
||||
const [isNewNote, setIsNewNote] = useState(false);
|
||||
const prevSyncStarted = usePrevious(syncStarted);
|
||||
const prevDecryptionStarted = usePrevious(decryptionStarted);
|
||||
const previousNoteId = usePrevious(formNote.id);
|
||||
const [resourceInfos, setResourceInfos] = useState<ResourceInfos>({});
|
||||
|
||||
// Increasing the value of this counter cancels any ongoing note refreshes and starts
|
||||
// a new refresh.
|
||||
const [formNoteRefeshScheduled, setFormNoteRefreshScheduled] = useState<number>(0);
|
||||
|
||||
async function initNoteState(n: any) {
|
||||
let originalCss = '';
|
||||
|
||||
@@ -106,14 +114,7 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// Check that synchronisation has just finished - and
|
||||
// if the note has never been changed, we reload it.
|
||||
// If the note has already been changed, it's a conflict
|
||||
// that's already been handled by the synchronizer.
|
||||
|
||||
if (!prevSyncStarted) return () => {};
|
||||
if (syncStarted) return () => {};
|
||||
if (formNote.hasChanged) return () => {};
|
||||
if (formNoteRefeshScheduled <= 0) return () => {};
|
||||
|
||||
reg.logger().info('Sync has finished and note has never been changed - reloading it');
|
||||
|
||||
@@ -132,6 +133,7 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
}
|
||||
|
||||
await initNoteState(n);
|
||||
setFormNoteRefreshScheduled(0);
|
||||
};
|
||||
|
||||
void loadNote();
|
||||
@@ -139,8 +141,34 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
|
||||
}, [prevSyncStarted, syncStarted, formNote]);
|
||||
}, [formNoteRefeshScheduled, noteId]);
|
||||
|
||||
const refreshFormNote = useCallback(() => {
|
||||
// Increase the counter to cancel any ongoing refresh attempts
|
||||
// and start a new one.
|
||||
setFormNoteRefreshScheduled(formNoteRefeshScheduled + 1);
|
||||
}, [formNoteRefeshScheduled]);
|
||||
|
||||
useEffect(() => {
|
||||
// Check that synchronisation has just finished - and
|
||||
// if the note has never been changed, we reload it.
|
||||
// If the note has already been changed, it's a conflict
|
||||
// that's already been handled by the synchronizer.
|
||||
const decryptionJustEnded = prevDecryptionStarted && !decryptionStarted;
|
||||
const syncJustEnded = prevSyncStarted && !syncStarted;
|
||||
|
||||
if (!decryptionJustEnded && !syncJustEnded) return;
|
||||
if (formNote.hasChanged) return;
|
||||
|
||||
// Refresh the form note.
|
||||
// This is kept separate from the above logic so that when prevSyncStarted is changed
|
||||
// from true to false, it doesn't cancel the note from loading.
|
||||
refreshFormNote();
|
||||
}, [
|
||||
prevSyncStarted, syncStarted,
|
||||
prevDecryptionStarted, decryptionStarted,
|
||||
formNote.hasChanged, refreshFormNote,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!noteId) {
|
||||
|
||||
@@ -84,11 +84,11 @@ function NoteListItem(props: NoteListItemProps, ref: any) {
|
||||
dragItemPosition = 'bottom';
|
||||
}
|
||||
|
||||
const onTitleClick = useCallback((event) => {
|
||||
const onTitleClick = useCallback((event: any) => {
|
||||
props.onTitleClick(event, props.item);
|
||||
}, [props.onTitleClick, props.item]);
|
||||
|
||||
const onCheckboxClick = useCallback((event) => {
|
||||
const onCheckboxClick = useCallback((event: any) => {
|
||||
props.onCheckboxClick(event, props.item);
|
||||
}, [props.onCheckboxClick, props.item]);
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ class NotePropertiesDialog extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
public async saveProperty() {
|
||||
if (!this.state.editedKey) return;
|
||||
if (!this.state.editedKey) return null;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
return new Promise((resolve: Function) => {
|
||||
|
||||
@@ -1,19 +1,37 @@
|
||||
/* eslint-disable jest/require-top-level-describe */
|
||||
|
||||
const { default: Logger, TargetType } = require('@joplin/utils/Logger');
|
||||
|
||||
// TODO: Some libraries required by test-utils.js seem to fail to import with the
|
||||
// jsdom environment.
|
||||
//
|
||||
// Thus, require('@joplin/lib/testing/test-utils.js') fails and some setup must be
|
||||
// copied.
|
||||
|
||||
const logger = new Logger();
|
||||
logger.addTarget(TargetType.Console);
|
||||
logger.setLevel(Logger.LEVEL_WARN);
|
||||
Logger.initializeGlobalLogger(logger);
|
||||
const { shimInit } = require('@joplin/lib/shim-init-node');
|
||||
const sqlite3 = require('sqlite3');
|
||||
const SyncTargetNone = require('@joplin/lib/SyncTargetNone').default;
|
||||
|
||||
// Mock the S3 sync target -- the @aws-s3 libraries depend on an old version
|
||||
// of uuid that doesn't work with jest without additional configuration.
|
||||
jest.doMock('@joplin/lib/SyncTargetAmazonS3', () => {
|
||||
return SyncTargetNone;
|
||||
});
|
||||
|
||||
// @electron/remote requires electron to be running. Mock it.
|
||||
jest.mock('@electron/remote', () => {
|
||||
return { require };
|
||||
return {
|
||||
require: () => {
|
||||
return {
|
||||
default: {},
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// Import after mocking problematic libraries
|
||||
const { afterEachCleanUp, afterAllCleanUp } = require('@joplin/lib/testing/test-utils.js');
|
||||
|
||||
|
||||
shimInit({ nodeSqlite: sqlite3 });
|
||||
|
||||
afterEach(async () => {
|
||||
await afterEachCleanUp();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await afterAllCleanUp();
|
||||
});
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ const EncryptionService = require('@joplin/lib/services/e2ee/EncryptionService')
|
||||
const { FileApiDriverLocal } = require('@joplin/lib/file-api-driver-local');
|
||||
const React = require('react');
|
||||
const nodeSqlite = require('sqlite3');
|
||||
const initLib = require('@joplin/lib/initLib').default;
|
||||
|
||||
// Security: If we attempt to navigate away from the root HTML page, it's likely because
|
||||
// of an improperly sanitized link. Prevent this by closing the window before we can
|
||||
@@ -132,6 +133,10 @@ document.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
const logger = new Logger();
|
||||
Logger.initializeGlobalLogger(logger);
|
||||
initLib(logger);
|
||||
|
||||
app().start(bridge().processArgv()).then((result) => {
|
||||
if (!result || !result.action) {
|
||||
require('./gui/Root');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "2.12.10",
|
||||
"version": "2.12.11",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
@@ -110,21 +110,21 @@
|
||||
"@electron/rebuild": "3.2.13",
|
||||
"@joplin/tools": "~2.12",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/node": "18.15.13",
|
||||
"@types/react": "16.14.41",
|
||||
"@types/jest": "29.5.3",
|
||||
"@types/node": "18.16.18",
|
||||
"@types/react": "18.0.24",
|
||||
"@types/react-redux": "7.1.25",
|
||||
"@types/styled-components": "5.1.26",
|
||||
"electron": "25.3.1",
|
||||
"electron-builder": "24.4.0",
|
||||
"glob": "10.2.7",
|
||||
"glob": "10.3.3",
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.5.0",
|
||||
"jest-environment-jsdom": "29.5.0",
|
||||
"js-sha512": "0.8.0",
|
||||
"nan": "2.17.0",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "5.0.2"
|
||||
"typescript": "5.1.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"7zip-bin-linux": "^1.0.1",
|
||||
@@ -162,8 +162,8 @@
|
||||
"react": "18.2.0",
|
||||
"react-datetime": "3.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-redux": "8.1.1",
|
||||
"react-select": "5.7.3",
|
||||
"react-redux": "8.1.2",
|
||||
"react-select": "5.7.4",
|
||||
"react-toggle-button": "2.2.0",
|
||||
"react-tooltip": "4.5.1",
|
||||
"redux": "4.2.1",
|
||||
|
||||
@@ -73,7 +73,7 @@ export default async (params: Params) => {
|
||||
teamId: process.env.APPLE_ASC_PROVIDER,
|
||||
|
||||
tool: 'notarytool',
|
||||
});
|
||||
} as any);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +1,23 @@
|
||||
import { fileExtension } from '@joplin/lib/path-utils';
|
||||
import shim from '@joplin/lib/shim';
|
||||
|
||||
export interface CheckForUpdateOptions {
|
||||
includePreReleases?: boolean;
|
||||
}
|
||||
|
||||
interface GitHubReleaseAsset {
|
||||
name: string;
|
||||
browser_download_url: string;
|
||||
}
|
||||
|
||||
export interface GitHubRelease {
|
||||
tag_name: string;
|
||||
prerelease: boolean;
|
||||
body: string;
|
||||
assets: {
|
||||
name: string;
|
||||
browser_download_url: string;
|
||||
}[];
|
||||
assets: GitHubReleaseAsset[];
|
||||
html_url: string;
|
||||
}
|
||||
|
||||
interface Release {
|
||||
export interface Release {
|
||||
version: string;
|
||||
prerelease: boolean;
|
||||
downloadUrl: string;
|
||||
@@ -24,13 +25,17 @@ interface Release {
|
||||
pageUrl: string;
|
||||
}
|
||||
|
||||
export type Platform = typeof process.platform;
|
||||
|
||||
export type Architecture = typeof process.arch;
|
||||
|
||||
function getMajorMinorTagName(tagName: string) {
|
||||
const s = tagName.split('.');
|
||||
s.pop();
|
||||
return s.join('.');
|
||||
}
|
||||
|
||||
export const extractVersionInfo = (releases: GitHubRelease[], platform: typeof process.platform, options: CheckForUpdateOptions) => {
|
||||
export const extractVersionInfo = (releases: GitHubRelease[], platform: Platform, arch: Architecture, portable: boolean, options: CheckForUpdateOptions) => {
|
||||
options = { includePreReleases: false, ...options };
|
||||
|
||||
if (!releases.length) throw new Error('Cannot get latest release info (JSON)');
|
||||
@@ -67,28 +72,43 @@ export const extractVersionInfo = (releases: GitHubRelease[], platform: typeof p
|
||||
}
|
||||
}
|
||||
|
||||
let downloadUrl = null;
|
||||
for (let i = 0; i < release.assets.length; i++) {
|
||||
const asset = release.assets[i];
|
||||
let found = false;
|
||||
const ext = fileExtension(asset.name);
|
||||
if (platform === 'win32' && ext === 'exe') {
|
||||
if (shim.isPortable()) {
|
||||
found = asset.name === 'JoplinPortable.exe';
|
||||
} else {
|
||||
found = !!asset.name.match(/^Joplin-Setup-[\d.]+\.exe$/);
|
||||
}
|
||||
} else if (platform === 'darwin' && ext === 'dmg' && !asset.name.endsWith('arm64.dmg')) { // We don't return the arm64 version for now
|
||||
found = true;
|
||||
} else if (platform === 'linux' && ext === '.AppImage') {
|
||||
found = true;
|
||||
}
|
||||
let foundAsset: GitHubReleaseAsset = null;
|
||||
|
||||
if (found) {
|
||||
downloadUrl = asset.browser_download_url.replace('github.com/laurent22/joplin/releases/download', 'objects.joplinusercontent.com');
|
||||
downloadUrl.concat('?source=DesktopApp&type=Update');
|
||||
break;
|
||||
}
|
||||
if (platform === 'win32' && portable) {
|
||||
foundAsset = release.assets.find(asset => {
|
||||
return asset.name === 'JoplinPortable.exe';
|
||||
});
|
||||
}
|
||||
|
||||
if (!foundAsset && platform === 'win32') {
|
||||
foundAsset = release.assets.find(asset => {
|
||||
return !!asset.name.match(/^Joplin-Setup-[\d.]+\.exe$/);
|
||||
});
|
||||
}
|
||||
|
||||
if (platform === 'darwin' && arch === 'arm64') {
|
||||
foundAsset = release.assets.find(asset => {
|
||||
return asset.name.endsWith('arm64.dmg');
|
||||
});
|
||||
}
|
||||
|
||||
if (!foundAsset && platform === 'darwin') {
|
||||
foundAsset = release.assets.find(asset => {
|
||||
return fileExtension(asset.name) === 'dmg' && !asset.name.endsWith('arm64.dmg');
|
||||
});
|
||||
}
|
||||
|
||||
if (platform === 'linux') {
|
||||
foundAsset = release.assets.find(asset => {
|
||||
return fileExtension(asset.name) === 'AppImage';
|
||||
});
|
||||
}
|
||||
|
||||
let downloadUrl: string = null;
|
||||
|
||||
if (foundAsset) {
|
||||
downloadUrl = foundAsset.browser_download_url.replace('github.com/laurent22/joplin/releases/download', 'objects.joplinusercontent.com');
|
||||
downloadUrl.concat('?source=DesktopApp&type=Update');
|
||||
}
|
||||
|
||||
function cleanUpReleaseNotes(releaseNotes: string[]) {
|
||||
|
||||
5155
packages/app-desktop/utils/checkForUpdatesUtilsTestData.ts
Normal file
5155
packages/app-desktop/utils/checkForUpdatesUtilsTestData.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -110,11 +110,11 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097717
|
||||
versionName "2.12.0"
|
||||
// ndk {
|
||||
// abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
// }
|
||||
versionCode 2097720
|
||||
versionName "2.12.3"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
}
|
||||
|
||||
// https://github.com/react-native-community/react-native-camera/issues/2138
|
||||
missingDimensionStrategy 'react-native-camera', 'general'
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATION" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
plugins: ['react-native-reanimated/plugin'],
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const React = require('react');
|
||||
|
||||
import { ReactElement, useCallback, useState } from 'react';
|
||||
import { ReactElement, useCallback, useMemo, useState } from 'react';
|
||||
import { LayoutChangeEvent, ScrollView, View, ViewStyle } from 'react-native';
|
||||
import ToggleOverflowButton from './ToggleOverflowButton';
|
||||
import ToolbarButton, { buttonSize } from './ToolbarButton';
|
||||
@@ -18,19 +18,22 @@ const Toolbar = (props: ToolbarProps) => {
|
||||
const [overflowButtonsVisible, setOverflowPopupVisible] = useState(false);
|
||||
const [maxButtonsEachSide, setMaxButtonsEachSide] = useState(0);
|
||||
|
||||
const allButtonSpecs = props.buttons.reduce((accumulator: ButtonSpec[], current: ButtonGroup) => {
|
||||
const newItems: ButtonSpec[] = [];
|
||||
for (const item of current.items) {
|
||||
if (item.visible ?? true) {
|
||||
newItems.push(item);
|
||||
const allButtonSpecs = useMemo(() => {
|
||||
const buttons = props.buttons.reduce((accumulator: ButtonSpec[], current: ButtonGroup) => {
|
||||
const newItems: ButtonSpec[] = [];
|
||||
for (const item of current.items) {
|
||||
if (item.visible ?? true) {
|
||||
newItems.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator.concat(...newItems);
|
||||
}, []);
|
||||
return accumulator.concat(...newItems);
|
||||
}, []);
|
||||
|
||||
// Sort from highest priority to lowest
|
||||
allButtonSpecs.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
||||
// Sort from highest priority to lowest
|
||||
buttons.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
||||
return buttons;
|
||||
}, [props.buttons]);
|
||||
|
||||
const allButtonComponents: ReactElement[] = [];
|
||||
let key = 0;
|
||||
@@ -67,7 +70,9 @@ const Toolbar = (props: ToolbarProps) => {
|
||||
);
|
||||
|
||||
const mainButtons: ReactElement[] = [];
|
||||
if (maxButtonsEachSide < allButtonComponents.length) {
|
||||
if (maxButtonsEachSide >= allButtonComponents.length) {
|
||||
mainButtons.push(...allButtonComponents);
|
||||
} else if (maxButtonsEachSide > 0) {
|
||||
// We want the menu to look something like this:
|
||||
// B I (…) 🔍 ⌨
|
||||
// where (…) shows/hides overflow.
|
||||
@@ -77,7 +82,7 @@ const Toolbar = (props: ToolbarProps) => {
|
||||
mainButtons.push(toggleOverflowButton);
|
||||
mainButtons.push(...allButtonComponents.slice(-maxButtonsEachSide));
|
||||
} else {
|
||||
mainButtons.push(...allButtonComponents);
|
||||
mainButtons.push(toggleOverflowButton);
|
||||
}
|
||||
|
||||
const styles = props.styleSheet.styles;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { describe, it, expect, beforeEach } from '@jest/globals';
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react-native';
|
||||
import '@testing-library/jest-native';
|
||||
|
||||
import NoteEditor from './NoteEditor';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { MenuProvider } from 'react-native-popup-menu';
|
||||
import { setupDatabaseAndSynchronizer, switchClient } from '@joplin/lib/testing/test-utils';
|
||||
|
||||
describe('NoteEditor', () => {
|
||||
beforeEach(async () => {
|
||||
// Required to use ExtendedWebView
|
||||
await setupDatabaseAndSynchronizer(0);
|
||||
await switchClient(0);
|
||||
});
|
||||
|
||||
it('should hide the markdown toolbar when the window is small', async () => {
|
||||
const wrappedNoteEditor = render(
|
||||
<MenuProvider>
|
||||
<NoteEditor
|
||||
themeId={Setting.THEME_ARITIM_DARK}
|
||||
initialText='Testing...'
|
||||
style={{}}
|
||||
toolbarEnabled={true}
|
||||
readOnly={false}
|
||||
onChange={()=>{}}
|
||||
onSelectionChange={()=>{}}
|
||||
onUndoRedoDepthChange={()=>{}}
|
||||
onAttach={()=>{}}
|
||||
/>
|
||||
</MenuProvider>
|
||||
);
|
||||
|
||||
// Maps from screen height to whether the markdown toolbar should be visible.
|
||||
const testCases: [number, boolean][] = [
|
||||
[10, false],
|
||||
[1000, true],
|
||||
[100, false],
|
||||
[80, false],
|
||||
[600, true],
|
||||
];
|
||||
|
||||
const noteEditorRoot = await wrappedNoteEditor.findByTestId('note-editor-root');
|
||||
|
||||
const setRootHeight = (height: number) => {
|
||||
act(() => {
|
||||
// See https://stackoverflow.com/a/61774123
|
||||
fireEvent(noteEditorRoot, 'layout', {
|
||||
nativeEvent: {
|
||||
layout: { height },
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
for (const [height, visible] of testCases) {
|
||||
setRootHeight(height);
|
||||
|
||||
await waitFor(async () => {
|
||||
const showMoreButton = await screen.queryByLabelText(_('Show more actions'));
|
||||
if (visible) {
|
||||
expect(showMoreButton).not.toBeNull();
|
||||
} else {
|
||||
expect(showMoreButton).toBeNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -8,7 +8,7 @@ import ExtendedWebView from '../ExtendedWebView';
|
||||
const React = require('react');
|
||||
import { forwardRef, RefObject, useImperativeHandle } from 'react';
|
||||
import { useEffect, useMemo, useState, useCallback, useRef } from 'react';
|
||||
import { View, ViewStyle } from 'react-native';
|
||||
import { LayoutChangeEvent, View, ViewStyle } from 'react-native';
|
||||
const { editorFont } = require('../global-style');
|
||||
|
||||
import SelectionFormatting from './SelectionFormatting';
|
||||
@@ -368,6 +368,19 @@ function NoteEditor(props: Props, ref: any) {
|
||||
console.error('NoteEditor: webview error');
|
||||
}, []);
|
||||
|
||||
const [hasSpaceForToolbar, setHasSpaceForToolbar] = useState(true);
|
||||
const toolbarEnabled = props.toolbarEnabled && hasSpaceForToolbar;
|
||||
|
||||
const onContainerLayout = useCallback((event: LayoutChangeEvent) => {
|
||||
const containerHeight = event.nativeEvent.layout.height;
|
||||
|
||||
if (containerHeight < 140) {
|
||||
setHasSpaceForToolbar(false);
|
||||
} else {
|
||||
setHasSpaceForToolbar(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toolbar = <MarkdownToolbar
|
||||
style={{
|
||||
// Don't show the markdown toolbar if there isn't enough space
|
||||
@@ -385,10 +398,14 @@ function NoteEditor(props: Props, ref: any) {
|
||||
// - `scrollEnabled` prevents iOS from scrolling the document (has no effect on Android)
|
||||
// when an editable region (e.g. a the full-screen NoteEditor) is focused.
|
||||
return (
|
||||
<View style={{
|
||||
...props.style,
|
||||
flexDirection: 'column',
|
||||
}}>
|
||||
<View
|
||||
testID='note-editor-root'
|
||||
onLayout={onContainerLayout}
|
||||
style={{
|
||||
...props.style,
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<EditLinkDialog
|
||||
visible={linkDialogVisible}
|
||||
themeId={props.themeId}
|
||||
@@ -419,7 +436,7 @@ function NoteEditor(props: Props, ref: any) {
|
||||
searchState={searchState}
|
||||
/>
|
||||
|
||||
{props.toolbarEnabled ? toolbar : null}
|
||||
{toolbarEnabled ? toolbar : null}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -601,7 +601,9 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
|
||||
!menuOptionComponents.length || !showContextMenuButton ? null : (
|
||||
<Menu onSelect={value => this.menu_select(value)} style={this.styles().contextMenu}>
|
||||
<MenuTrigger style={contextMenuStyle}>
|
||||
<Icon name="md-ellipsis-vertical" style={this.styles().contextMenuTrigger} />
|
||||
<View accessibilityLabel={_('Actions')}>
|
||||
<Icon name="md-ellipsis-vertical" style={this.styles().contextMenuTrigger} />
|
||||
</View>
|
||||
</MenuTrigger>
|
||||
<MenuOptions>
|
||||
<ScrollView style={{ maxHeight: windowHeight }}>{menuOptionComponents}</ScrollView>
|
||||
|
||||
22
packages/app-mobile/components/SideMenu.ts
Normal file
22
packages/app-mobile/components/SideMenu.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
const { connect } = require('react-redux');
|
||||
const SideMenu_ = require('react-native-side-menu-updated').default;
|
||||
import { Dimensions } from 'react-native';
|
||||
import { State } from '@joplin/lib/reducer';
|
||||
|
||||
class SideMenuComponent extends SideMenu_ {
|
||||
public onLayoutChange(e: any) {
|
||||
const { width, height } = e.nativeEvent.layout;
|
||||
const openMenuOffsetPercentage = this.props.openMenuOffset / Dimensions.get('window').width;
|
||||
const openMenuOffset = width * openMenuOffsetPercentage;
|
||||
const hiddenMenuOffset = width * this.state.hiddenMenuOffsetPercentage;
|
||||
this.setState({ width, height, openMenuOffset, hiddenMenuOffset });
|
||||
}
|
||||
}
|
||||
|
||||
const SideMenu = connect((state: State) => {
|
||||
return {
|
||||
isOpen: state.showSideMenu,
|
||||
};
|
||||
})(SideMenuComponent);
|
||||
|
||||
export default SideMenu;
|
||||
@@ -20,7 +20,7 @@ const { _ } = require('@joplin/lib/locale');
|
||||
const { BaseScreenComponent } = require('../../base-screen.js');
|
||||
const { Dropdown } = require('../../Dropdown');
|
||||
const { themeStyle } = require('../../global-style.js');
|
||||
const shared = require('@joplin/lib/components/shared/config-shared.js');
|
||||
const shared = require('@joplin/lib/components/shared/config/config-shared.js');
|
||||
import SyncTargetRegistry from '@joplin/lib/SyncTargetRegistry';
|
||||
import { openDocumentTree } from '@joplin/react-native-saf-x';
|
||||
import biometricAuthenticate from '../../biometrics/biometricAuthenticate';
|
||||
|
||||
@@ -10,7 +10,8 @@ import { ChangeEvent, UndoRedoDepthChangeEvent } from '../NoteEditor/types';
|
||||
|
||||
const FileViewer = require('react-native-file-viewer').default;
|
||||
const React = require('react');
|
||||
const { Platform, Keyboard, View, TextInput, StyleSheet, Linking, Image, Share, PermissionsAndroid } = require('react-native');
|
||||
const { Keyboard, View, TextInput, StyleSheet, Linking, Image, Share } = require('react-native');
|
||||
import { Platform, PermissionsAndroid } from 'react-native';
|
||||
const { connect } = require('react-redux');
|
||||
// const { MarkdownEditor } = require('@joplin/lib/../MarkdownEditor/index.js');
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
@@ -36,7 +37,7 @@ const { BaseScreenComponent } = require('../base-screen.js');
|
||||
const { themeStyle, editorFont } = require('../global-style.js');
|
||||
const { dialogs } = require('../../utils/dialogs.js');
|
||||
const DialogBox = require('react-native-dialogbox').default;
|
||||
const ImageResizer = require('react-native-image-resizer').default;
|
||||
import ImageResizer from '@bam.tech/react-native-image-resizer';
|
||||
import shared from '@joplin/lib/components/shared/note-screen-shared';
|
||||
import { ImagePickerResponse, launchImageLibrary } from 'react-native-image-picker';
|
||||
import SelectDateTimeDialog from '../SelectDateTimeDialog';
|
||||
@@ -572,34 +573,30 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
|
||||
public async resizeImage(localFilePath: string, targetPath: string, mimeType: string) {
|
||||
const maxSize = Resource.IMAGE_MAX_DIMENSION;
|
||||
|
||||
const dimensions: any = await this.imageDimensions(localFilePath);
|
||||
|
||||
reg.logger().info('Original dimensions ', dimensions);
|
||||
|
||||
let mustResize = dimensions.width > maxSize || dimensions.height > maxSize;
|
||||
|
||||
if (mustResize) {
|
||||
const buttonId = await dialogs.pop(this, _('You are about to attach a large image (%dx%d pixels). Would you like to resize it down to %d pixels before attaching it?', dimensions.width, dimensions.height, maxSize), [
|
||||
{ text: _('Yes'), id: 'yes' },
|
||||
{ text: _('No'), id: 'no' },
|
||||
{ text: _('Cancel'), id: 'cancel' },
|
||||
]);
|
||||
|
||||
if (buttonId === 'cancel') return false;
|
||||
|
||||
mustResize = buttonId === 'yes';
|
||||
}
|
||||
|
||||
if (mustResize) {
|
||||
const saveOriginalImage = async () => {
|
||||
await shim.fsDriver().copy(localFilePath, targetPath);
|
||||
return true;
|
||||
};
|
||||
const saveResizedImage = async () => {
|
||||
dimensions.width = maxSize;
|
||||
dimensions.height = maxSize;
|
||||
|
||||
reg.logger().info('New dimensions ', dimensions);
|
||||
|
||||
const format = mimeType === 'image/png' ? 'PNG' : 'JPEG';
|
||||
reg.logger().info(`Resizing image ${localFilePath}`);
|
||||
const resizedImage = await ImageResizer.createResizedImage(localFilePath, dimensions.width, dimensions.height, format, 85); // , 0, targetPath);
|
||||
const resizedImage = await ImageResizer.createResizedImage(
|
||||
localFilePath,
|
||||
dimensions.width,
|
||||
dimensions.height,
|
||||
format,
|
||||
85, // quality
|
||||
undefined, // rotation
|
||||
undefined, // outputPath
|
||||
true // keep metadata
|
||||
);
|
||||
|
||||
const resizedImagePath = resizedImage.uri;
|
||||
reg.logger().info('Resized image ', resizedImagePath);
|
||||
@@ -612,11 +609,27 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
} catch (error) {
|
||||
reg.logger().warn('Error when unlinking cached file: ', error);
|
||||
}
|
||||
} else {
|
||||
await shim.fsDriver().copy(localFilePath, targetPath);
|
||||
return true;
|
||||
};
|
||||
|
||||
const canResize = dimensions.width > maxSize || dimensions.height > maxSize;
|
||||
if (canResize) {
|
||||
const resizeLargeImages = Setting.value('imageResizing');
|
||||
if (resizeLargeImages === 'alwaysAsk') {
|
||||
const userAnswer = await dialogs.pop(this, `${_('You are about to attach a large image (%dx%d pixels). Would you like to resize it down to %d pixels before attaching it?', dimensions.width, dimensions.height, maxSize)}\n\n${_('(You may disable this prompt in the options)')}`, [
|
||||
{ text: _('Yes'), id: 'yes' },
|
||||
{ text: _('No'), id: 'no' },
|
||||
{ text: _('Cancel'), id: 'cancel' },
|
||||
]);
|
||||
if (userAnswer === 'yes') return await saveResizedImage();
|
||||
if (userAnswer === 'no') return await saveOriginalImage();
|
||||
if (userAnswer === 'cancel') return false;
|
||||
} else if (resizeLargeImages === 'alwaysResize') {
|
||||
return await saveResizedImage();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return await saveOriginalImage();
|
||||
}
|
||||
|
||||
public async attachFile(pickerResponse: any, fileType: string) {
|
||||
@@ -795,8 +808,12 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
|
||||
public async onAlarmDialogAccept(date: Date) {
|
||||
const response = await checkPermissions(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
|
||||
if (response !== PermissionsAndroid.RESULTS.GRANTED) {
|
||||
logger.warn('POST_NOTIFICATION permission was not granted');
|
||||
|
||||
// The POST_NOTIFICATIONS permission isn't supported on Android API < 33.
|
||||
// (If unsupported, returns NEVER_ASK_AGAIN).
|
||||
// On earlier releases, notifications should work without this permission.
|
||||
if (response === PermissionsAndroid.RESULTS.DENIED) {
|
||||
logger.warn('POST_NOTIFICATIONS permission was not granted');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,10 @@ class SearchScreenComponent extends BaseScreenComponent {
|
||||
selectionColor={theme.textSelectionColor}
|
||||
keyboardAppearance={theme.keyboardAppearance}
|
||||
/>
|
||||
<TouchableHighlight onPress={() => this.clearButton_press()}>
|
||||
<TouchableHighlight
|
||||
onPress={() => this.clearButton_press()}
|
||||
accessibilityLabel={_('Clear')}
|
||||
>
|
||||
<Icon name="md-close-circle" style={this.styles().clearIcon} />
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
|
||||
@@ -23,6 +23,7 @@ Icon.loadFont().catch((error: any) => { console.info(error); });
|
||||
interface Props {
|
||||
syncStarted: boolean;
|
||||
themeId: number;
|
||||
sideMenuVisible: boolean;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
dispatch: Function;
|
||||
collapsedFolderIds: string[];
|
||||
@@ -491,15 +492,29 @@ const SideMenuContentComponent = (props: Props) => {
|
||||
items = items.concat(folderItems);
|
||||
}
|
||||
|
||||
const isHidden = !props.sideMenuVisible;
|
||||
|
||||
const style = {
|
||||
flex: 1,
|
||||
borderRightWidth: 1,
|
||||
borderRightColor: theme.dividerColor,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
|
||||
// Have the UI reflect whether the View is hidden to the screen reader.
|
||||
// This way, there will be visual feedback if isHidden is incorrect.
|
||||
opacity: isHidden ? 0.5 : undefined,
|
||||
};
|
||||
|
||||
// Note: iOS uses accessibilityElementsHidden and Android uses importantForAccessibility
|
||||
// to hide elements from the screenreader.
|
||||
|
||||
return (
|
||||
<View style={style}>
|
||||
<View
|
||||
style={style}
|
||||
|
||||
accessibilityElementsHidden={isHidden}
|
||||
importantForAccessibility={isHidden ? 'no-hide-descendants' : undefined}
|
||||
>
|
||||
<View style={{ flex: 1, opacity: props.opacity }}>
|
||||
<ScrollView scrollsToTop={false} style={styles_.menu}>
|
||||
{items}
|
||||
@@ -520,6 +535,7 @@ export default connect((state: AppState) => {
|
||||
notesParentType: state.notesParentType,
|
||||
locale: state.settings.locale,
|
||||
themeId: state.settings.theme,
|
||||
sideMenuVisible: state.showSideMenu,
|
||||
// Don't do the opacity animation as it means re-rendering the list multiple times
|
||||
// opacity: state.sideMenuOpenPercent,
|
||||
collapsedFolderIds: state.collapsedFolderIds,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { Banner, ActivityIndicator, Modal } from 'react-native-paper';
|
||||
import { Banner, ActivityIndicator } from 'react-native-paper';
|
||||
import { _, languageName } from '@joplin/lib/locale';
|
||||
import useAsyncEffect, { AsyncEffectEvent } from '@joplin/lib/hooks/useAsyncEffect';
|
||||
import { getVosk, Recorder, startRecording, Vosk } from '../../services/voiceTyping/vosk';
|
||||
@@ -107,18 +107,16 @@ export default (props: Props) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal visible={true} style={{ display: 'flex', flexDirection: 'column', justifyContent: 'flex-end' }}>
|
||||
<Banner
|
||||
visible={true}
|
||||
icon={renderIcon()}
|
||||
actions={[
|
||||
{
|
||||
label: _('Done'),
|
||||
onPress: onDismiss,
|
||||
},
|
||||
]}>
|
||||
{`${_('Voice typing...')}\n${renderContent()}`}
|
||||
</Banner>
|
||||
</Modal>
|
||||
<Banner
|
||||
visible={true}
|
||||
icon={renderIcon()}
|
||||
actions={[
|
||||
{
|
||||
label: _('Done'),
|
||||
onPress: onDismiss,
|
||||
},
|
||||
]}>
|
||||
{`${_('Voice typing...')}\n${renderContent()}`}
|
||||
</Banner>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
import 'react-native-get-random-values';
|
||||
import 'react-native-url-polyfill/auto';
|
||||
|
||||
// Set up required for react-native-drawer-layout (See: https://reactnavigation.org/docs/drawer-layout/ v6.x)
|
||||
import 'react-native-gesture-handler';
|
||||
|
||||
import { LogBox, AppRegistry } from 'react-native';
|
||||
const Root = require('./root').default;
|
||||
|
||||
|
||||
@@ -381,16 +381,10 @@
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Joplin/Pods-Joplin-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-DoubleConversion/double-conversion.framework/double-conversion",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-Glog/glog.framework/glog",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/double-conversion.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -517,13 +511,13 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 94;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 12.12.0;
|
||||
MARKETING_VERSION = 12.12.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -546,12 +540,12 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 94;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 12.12.0;
|
||||
MARKETING_VERSION = 12.12.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -698,14 +692,14 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 94;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 12.12.0;
|
||||
MARKETING_VERSION = 12.12.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
|
||||
@@ -729,14 +723,14 @@
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 94;
|
||||
CURRENT_PROJECT_VERSION = 97;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 12.12.0;
|
||||
MARKETING_VERSION = 12.12.3;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
PODS:
|
||||
- boost (1.76.0)
|
||||
- CocoaAsyncSocket (7.6.5)
|
||||
- DoubleConversion (1.1.6)
|
||||
- FBLazyVector (0.71.10)
|
||||
- FBReactNativeSpec (0.71.10):
|
||||
@@ -10,67 +9,6 @@ PODS:
|
||||
- React-Core (= 0.71.10)
|
||||
- React-jsi (= 0.71.10)
|
||||
- ReactCommon/turbomodule/core (= 0.71.10)
|
||||
- Flipper (0.125.0):
|
||||
- Flipper-Folly (~> 2.6)
|
||||
- Flipper-RSocket (~> 1.4)
|
||||
- Flipper-Boost-iOSX (1.76.0.1.11)
|
||||
- Flipper-DoubleConversion (3.2.0.1)
|
||||
- Flipper-Fmt (7.1.7)
|
||||
- Flipper-Folly (2.6.10):
|
||||
- Flipper-Boost-iOSX
|
||||
- Flipper-DoubleConversion
|
||||
- Flipper-Fmt (= 7.1.7)
|
||||
- Flipper-Glog
|
||||
- libevent (~> 2.1.12)
|
||||
- OpenSSL-Universal (= 1.1.1100)
|
||||
- Flipper-Glog (0.5.0.5)
|
||||
- Flipper-PeerTalk (0.0.4)
|
||||
- Flipper-RSocket (1.4.3):
|
||||
- Flipper-Folly (~> 2.6)
|
||||
- FlipperKit (0.125.0):
|
||||
- FlipperKit/Core (= 0.125.0)
|
||||
- FlipperKit/Core (0.125.0):
|
||||
- Flipper (~> 0.125.0)
|
||||
- FlipperKit/CppBridge
|
||||
- FlipperKit/FBCxxFollyDynamicConvert
|
||||
- FlipperKit/FBDefines
|
||||
- FlipperKit/FKPortForwarding
|
||||
- SocketRocket (~> 0.6.0)
|
||||
- FlipperKit/CppBridge (0.125.0):
|
||||
- Flipper (~> 0.125.0)
|
||||
- FlipperKit/FBCxxFollyDynamicConvert (0.125.0):
|
||||
- Flipper-Folly (~> 2.6)
|
||||
- FlipperKit/FBDefines (0.125.0)
|
||||
- FlipperKit/FKPortForwarding (0.125.0):
|
||||
- CocoaAsyncSocket (~> 7.6)
|
||||
- Flipper-PeerTalk (~> 0.0.4)
|
||||
- FlipperKit/FlipperKitHighlightOverlay (0.125.0)
|
||||
- FlipperKit/FlipperKitLayoutHelpers (0.125.0):
|
||||
- FlipperKit/Core
|
||||
- FlipperKit/FlipperKitHighlightOverlay
|
||||
- FlipperKit/FlipperKitLayoutTextSearchable
|
||||
- FlipperKit/FlipperKitLayoutIOSDescriptors (0.125.0):
|
||||
- FlipperKit/Core
|
||||
- FlipperKit/FlipperKitHighlightOverlay
|
||||
- FlipperKit/FlipperKitLayoutHelpers
|
||||
- YogaKit (~> 1.18)
|
||||
- FlipperKit/FlipperKitLayoutPlugin (0.125.0):
|
||||
- FlipperKit/Core
|
||||
- FlipperKit/FlipperKitHighlightOverlay
|
||||
- FlipperKit/FlipperKitLayoutHelpers
|
||||
- FlipperKit/FlipperKitLayoutIOSDescriptors
|
||||
- FlipperKit/FlipperKitLayoutTextSearchable
|
||||
- YogaKit (~> 1.18)
|
||||
- FlipperKit/FlipperKitLayoutTextSearchable (0.125.0)
|
||||
- FlipperKit/FlipperKitNetworkPlugin (0.125.0):
|
||||
- FlipperKit/Core
|
||||
- FlipperKit/FlipperKitReactPlugin (0.125.0):
|
||||
- FlipperKit/Core
|
||||
- FlipperKit/FlipperKitUserDefaultsPlugin (0.125.0):
|
||||
- FlipperKit/Core
|
||||
- FlipperKit/SKIOSNetworkPlugin (0.125.0):
|
||||
- FlipperKit/Core
|
||||
- FlipperKit/FlipperKitNetworkPlugin
|
||||
- fmt (6.2.1)
|
||||
- glog (0.3.5)
|
||||
- hermes-engine (0.71.10):
|
||||
@@ -81,7 +19,6 @@ PODS:
|
||||
- JoplinCommonShareExtension
|
||||
- React
|
||||
- libevent (2.1.12)
|
||||
- OpenSSL-Universal (1.1.1100)
|
||||
- RCT-Folly (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
@@ -343,7 +280,7 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-camera/RN (4.2.1):
|
||||
- React-Core
|
||||
- react-native-document-picker (8.2.1):
|
||||
- react-native-document-picker (9.0.1):
|
||||
- React-Core
|
||||
- react-native-fingerprint-scanner (6.0.0):
|
||||
- React
|
||||
@@ -351,17 +288,17 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-get-random-values (1.9.0):
|
||||
- React-Core
|
||||
- react-native-image-picker (5.4.2):
|
||||
- react-native-image-picker (5.6.0):
|
||||
- React-Core
|
||||
- react-native-image-resizer (1.4.5):
|
||||
- react-native-image-resizer (3.0.5):
|
||||
- React-Core
|
||||
- react-native-netinfo (9.3.11):
|
||||
- react-native-netinfo (9.4.1):
|
||||
- React-Core
|
||||
- react-native-rsa-native (2.0.5):
|
||||
- React
|
||||
- react-native-saf-x (2.12.0):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (4.5.5):
|
||||
- react-native-safe-area-context (4.6.4):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
@@ -465,9 +402,9 @@ PODS:
|
||||
- React-Core
|
||||
- RNCPushNotificationIOS (1.11.0):
|
||||
- React-Core
|
||||
- RNDateTimePicker (7.1.0):
|
||||
- RNDateTimePicker (7.4.1):
|
||||
- React-Core
|
||||
- RNDeviceInfo (10.6.1):
|
||||
- RNDeviceInfo (10.7.0):
|
||||
- React-Core
|
||||
- RNExitApp (1.1.0):
|
||||
- React
|
||||
@@ -475,41 +412,10 @@ PODS:
|
||||
- React-Core
|
||||
- RNFS (2.20.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.12.0):
|
||||
- React-Core
|
||||
- RNLocalize (3.0.2):
|
||||
- React-Core
|
||||
- RNQuickAction (0.3.13):
|
||||
- React
|
||||
- RNReanimated (3.3.0):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-callinvoker
|
||||
- React-Core
|
||||
- React-Core/DevSupport
|
||||
- React-Core/RCTWebSocket
|
||||
- React-CoreModules
|
||||
- React-cxxreact
|
||||
- React-hermes
|
||||
- React-jsi
|
||||
- React-jsiexecutor
|
||||
- React-jsinspector
|
||||
- React-RCTActionSheet
|
||||
- React-RCTAnimation
|
||||
- React-RCTBlob
|
||||
- React-RCTImage
|
||||
- React-RCTLinking
|
||||
- React-RCTNetwork
|
||||
- React-RCTSettings
|
||||
- React-RCTText
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNSecureRandom (1.0.1):
|
||||
- React
|
||||
- RNShare (8.2.2):
|
||||
@@ -523,44 +429,19 @@ PODS:
|
||||
- RNZipArchive/Core (6.0.9):
|
||||
- React-Core
|
||||
- SSZipArchive (~> 2.2)
|
||||
- SocketRocket (0.6.0)
|
||||
- SSZipArchive (2.4.3)
|
||||
- Yoga (1.14.0)
|
||||
- YogaKit (1.18.1):
|
||||
- Yoga (~> 1.14)
|
||||
|
||||
DEPENDENCIES:
|
||||
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
|
||||
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
||||
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
|
||||
- Flipper (= 0.125.0)
|
||||
- Flipper-Boost-iOSX (= 1.76.0.1.11)
|
||||
- Flipper-DoubleConversion (= 3.2.0.1)
|
||||
- Flipper-Fmt (= 7.1.7)
|
||||
- Flipper-Folly (= 2.6.10)
|
||||
- Flipper-Glog (= 0.5.0.5)
|
||||
- Flipper-PeerTalk (= 0.0.4)
|
||||
- Flipper-RSocket (= 1.4.3)
|
||||
- FlipperKit (= 0.125.0)
|
||||
- FlipperKit/Core (= 0.125.0)
|
||||
- FlipperKit/CppBridge (= 0.125.0)
|
||||
- FlipperKit/FBCxxFollyDynamicConvert (= 0.125.0)
|
||||
- FlipperKit/FBDefines (= 0.125.0)
|
||||
- FlipperKit/FKPortForwarding (= 0.125.0)
|
||||
- FlipperKit/FlipperKitHighlightOverlay (= 0.125.0)
|
||||
- FlipperKit/FlipperKitLayoutPlugin (= 0.125.0)
|
||||
- FlipperKit/FlipperKitLayoutTextSearchable (= 0.125.0)
|
||||
- FlipperKit/FlipperKitNetworkPlugin (= 0.125.0)
|
||||
- FlipperKit/FlipperKitReactPlugin (= 0.125.0)
|
||||
- FlipperKit/FlipperKitUserDefaultsPlugin (= 0.125.0)
|
||||
- FlipperKit/SKIOSNetworkPlugin (= 0.125.0)
|
||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
|
||||
- JoplinCommonShareExtension (from `ShareExtension`)
|
||||
- JoplinRNShareExtension (from `ShareExtension`)
|
||||
- libevent (~> 2.1.12)
|
||||
- OpenSSL-Universal (= 1.1.1100)
|
||||
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
|
||||
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
|
||||
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
|
||||
@@ -568,7 +449,6 @@ DEPENDENCIES:
|
||||
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
|
||||
- React-Codegen (from `build/generated/ios`)
|
||||
- React-Core (from `../node_modules/react-native/`)
|
||||
- React-Core/DevSupport (from `../node_modules/react-native/`)
|
||||
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
|
||||
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
|
||||
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
|
||||
@@ -584,7 +464,7 @@ DEPENDENCIES:
|
||||
- "react-native-geolocation (from `../node_modules/@react-native-community/geolocation`)"
|
||||
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
|
||||
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
|
||||
- react-native-image-resizer (from `../node_modules/react-native-image-resizer`)
|
||||
- "react-native-image-resizer (from `../node_modules/@bam.tech/react-native-image-resizer`)"
|
||||
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
|
||||
- react-native-rsa-native (from `../node_modules/react-native-rsa-native`)
|
||||
- "react-native-saf-x (from `../node_modules/@joplin/react-native-saf-x`)"
|
||||
@@ -614,10 +494,8 @@ DEPENDENCIES:
|
||||
- RNExitApp (from `../node_modules/react-native-exit-app`)
|
||||
- RNFileViewer (from `../node_modules/react-native-file-viewer`)
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNLocalize (from `../node_modules/react-native-localize`)
|
||||
- RNQuickAction (from `../node_modules/react-native-quick-actions`)
|
||||
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||
- RNSecureRandom (from `../node_modules/react-native-securerandom`)
|
||||
- RNShare (from `../node_modules/react-native-share`)
|
||||
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
|
||||
@@ -626,22 +504,9 @@ DEPENDENCIES:
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- CocoaAsyncSocket
|
||||
- Flipper
|
||||
- Flipper-Boost-iOSX
|
||||
- Flipper-DoubleConversion
|
||||
- Flipper-Fmt
|
||||
- Flipper-Folly
|
||||
- Flipper-Glog
|
||||
- Flipper-PeerTalk
|
||||
- Flipper-RSocket
|
||||
- FlipperKit
|
||||
- fmt
|
||||
- libevent
|
||||
- OpenSSL-Universal
|
||||
- SocketRocket
|
||||
- SSZipArchive
|
||||
- YogaKit
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
boost:
|
||||
@@ -703,7 +568,7 @@ EXTERNAL SOURCES:
|
||||
react-native-image-picker:
|
||||
:path: "../node_modules/react-native-image-picker"
|
||||
react-native-image-resizer:
|
||||
:path: "../node_modules/react-native-image-resizer"
|
||||
:path: "../node_modules/@bam.tech/react-native-image-resizer"
|
||||
react-native-netinfo:
|
||||
:path: "../node_modules/@react-native-community/netinfo"
|
||||
react-native-rsa-native:
|
||||
@@ -762,14 +627,10 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-file-viewer"
|
||||
RNFS:
|
||||
:path: "../node_modules/react-native-fs"
|
||||
RNGestureHandler:
|
||||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNLocalize:
|
||||
:path: "../node_modules/react-native-localize"
|
||||
RNQuickAction:
|
||||
:path: "../node_modules/react-native-quick-actions"
|
||||
RNReanimated:
|
||||
:path: "../node_modules/react-native-reanimated"
|
||||
RNSecureRandom:
|
||||
:path: "../node_modules/react-native-securerandom"
|
||||
RNShare:
|
||||
@@ -783,26 +644,15 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
boost: 57d2868c099736d80fcd648bf211b4431e51a558
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: ddb55c55295ea51ed98aa7e2e08add2f826309d5
|
||||
FBReactNativeSpec: 90fc1a90b4b7a171e0a7c20ea426c1bf6ce4399c
|
||||
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
|
||||
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
|
||||
Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30
|
||||
Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b
|
||||
Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3
|
||||
Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446
|
||||
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
|
||||
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541
|
||||
FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||
hermes-engine: d27603b55a48402501ad1928c05411dae9cd6b85
|
||||
JoplinCommonShareExtension: a8b60b02704d85a7305627912c0240e94af78db7
|
||||
JoplinRNShareExtension: 485f3e6dad83b7b77f1572eabc249f869ee55c02
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
|
||||
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
|
||||
RCTRequired: 8ef706f91e2b643cd32c26a57700b5f24fab0585
|
||||
RCTTypeSafety: 5fbddd8eb9242b91ac0d901c01da3673f358b1b7
|
||||
@@ -819,16 +669,16 @@ SPEC CHECKSUMS:
|
||||
React-logger: ef2269b3afa6ba868da90496c3e17a4ec4f4cee0
|
||||
react-native-alarm-notification: 0732f97be04975a23ba60e675bdb961a0aaf6aa6
|
||||
react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f
|
||||
react-native-document-picker: 69ca2094d8780cfc1e7e613894d15290fdc54bba
|
||||
react-native-document-picker: 2b8f18667caee73a96708a82b284a4f40b30a156
|
||||
react-native-fingerprint-scanner: ac6656f18c8e45a7459302b84da41a44ad96dbbe
|
||||
react-native-geolocation: 0f7fe8a4c2de477e278b0365cce27d089a8c5903
|
||||
react-native-get-random-values: dee677497c6a740b71e5612e8dbd83e7539ed5bb
|
||||
react-native-image-picker: 77f552291e993f3fdcdf48cc3c280ef7f11789c8
|
||||
react-native-image-resizer: d9fb629a867335bdc13230ac2a58702bb8c8828f
|
||||
react-native-netinfo: 3a48f51c18dbd9253440621955e11de71bc51b32
|
||||
react-native-image-picker: db60857e03d63721f19b6f4027de20429ddd9cba
|
||||
react-native-image-resizer: 00ceb0e05586c7aadf061eea676957a6c2ec60fa
|
||||
react-native-netinfo: fefd4e98d75cbdd6e85fc530f7111a8afdf2b0c5
|
||||
react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
|
||||
react-native-saf-x: 129cd2ddf120a1f6164c724b2846d172666b33de
|
||||
react-native-safe-area-context: 33e71d7408dffe148b08968d97a524009634ccc8
|
||||
react-native-safe-area-context: 68b07eabfb0d14547d36f6929c0e98d818064f02
|
||||
react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d
|
||||
react-native-sqlite-storage: f6d515e1c446d1e6d026aa5352908a25d4de3261
|
||||
react-native-version-info: a106f23009ac0db4ee00de39574eb546682579b9
|
||||
@@ -849,23 +699,19 @@ SPEC CHECKSUMS:
|
||||
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
|
||||
RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495
|
||||
RNCPushNotificationIOS: 64218f3c776c03d7408284a819b2abfda1834bc8
|
||||
RNDateTimePicker: 7ecd54a97fc3749f38c3c89a171f6cbd52f3c142
|
||||
RNDeviceInfo: ab292735ad4fccc5f2aec0c773f7a7f03c7073ae
|
||||
RNDateTimePicker: 9b4091348e53f540180abdc54984d839a556f593
|
||||
RNDeviceInfo: 25d818c85db769cc0e7083d39efaa01a6f450df3
|
||||
RNExitApp: c4e052df2568b43bec8a37c7cd61194d4cfee2c3
|
||||
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
|
||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||
RNGestureHandler: dec4645026e7401a0899f2846d864403478ff6a5
|
||||
RNLocalize: dbea38dcb344bf80ff18a1757b1becf11f70cae4
|
||||
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
|
||||
RNReanimated: 9976fbaaeb8a188c36026154c844bf374b3b7eeb
|
||||
RNSecureRandom: 07efbdf2cd99efe13497433668e54acd7df49fef
|
||||
RNShare: d82e10f6b7677f4b0048c23709bd04098d5aee6c
|
||||
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
|
||||
RNZipArchive: 68a0c6db4b1c103f846f1559622050df254a3ade
|
||||
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
|
||||
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
|
||||
Yoga: e7ea9e590e27460d28911403b894722354d73479
|
||||
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
|
||||
|
||||
PODFILE CHECKSUM: 3b2cace838120977b5b54871752c9dddf5a11cea
|
||||
|
||||
|
||||
@@ -33,6 +33,21 @@ document.createRange = () => {
|
||||
|
||||
shimInit({ nodeSqlite: sqlite3 });
|
||||
|
||||
// This library has the following error when running within Jest:
|
||||
// Invariant Violation: `new NativeEventEmitter()` requires a non-null argument.
|
||||
jest.mock('react-native-device-info', () => {
|
||||
return {
|
||||
hasNotch: () => false,
|
||||
};
|
||||
});
|
||||
|
||||
// react-native-webview expects native iOS/Android code so needs to be mocked.
|
||||
jest.mock('react-native-webview', () => {
|
||||
const { View } = require('react-native');
|
||||
return {
|
||||
WebView: View,
|
||||
};
|
||||
});
|
||||
|
||||
// react-native-fs's CachesDirectoryPath export doesn't work in a testing environment.
|
||||
// Use a temporary folder instead.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"scripts": {
|
||||
"start": "BROWSERSLIST_IGNORE_OLD_DATA=true react-native start --reset-cache",
|
||||
"android": "react-native run-android",
|
||||
"build": "gulp build",
|
||||
"build": "NO_FLIPPER=1 gulp build",
|
||||
"tsc": "tsc --project tsconfig.json",
|
||||
"watch": "tsc --watch --preserveWatchOutput --project tsconfig.json",
|
||||
"clean": "node tools/clean.js",
|
||||
@@ -18,15 +18,16 @@
|
||||
"postinstall": "jetify && yarn run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bam.tech/react-native-image-resizer": "3.0.5",
|
||||
"@joplin/lib": "~2.12",
|
||||
"@joplin/react-native-alarm-notification": "~2.12",
|
||||
"@joplin/react-native-saf-x": "~2.12",
|
||||
"@joplin/renderer": "~2.12",
|
||||
"@joplin/utils": "~2.12",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/datetimepicker": "7.1.0",
|
||||
"@react-native-community/datetimepicker": "7.4.1",
|
||||
"@react-native-community/geolocation": "3.0.6",
|
||||
"@react-native-community/netinfo": "9.3.11",
|
||||
"@react-native-community/netinfo": "9.4.1",
|
||||
"@react-native-community/push-notification-ios": "1.11.0",
|
||||
"@react-native-community/slider": "4.4.2",
|
||||
"assert-browserify": "2.0.0",
|
||||
@@ -43,31 +44,27 @@
|
||||
"punycode": "2.3.0",
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.71.10",
|
||||
"react-native-action-button": "2.8.5",
|
||||
"react-native-camera": "4.2.1",
|
||||
"react-native-device-info": "10.6.1",
|
||||
"react-native-device-info": "10.7.0",
|
||||
"react-native-dialogbox": "0.6.10",
|
||||
"react-native-document-picker": "8.2.1",
|
||||
"react-native-drawer-layout": "3.2.1",
|
||||
"react-native-document-picker": "9.0.1",
|
||||
"react-native-dropdownalert": "4.5.1",
|
||||
"react-native-exit-app": "1.1.0",
|
||||
"react-native-file-viewer": "2.1.5",
|
||||
"react-native-fingerprint-scanner": "6.0.0",
|
||||
"react-native-fs": "2.20.0",
|
||||
"react-native-gesture-handler": "2.12.0",
|
||||
"react-native-get-random-values": "1.9.0",
|
||||
"react-native-image-picker": "5.6.0",
|
||||
"react-native-image-resizer": "1.4.5",
|
||||
"react-native-localize": "3.0.2",
|
||||
"react-native-modal-datetime-picker": "15.0.1",
|
||||
"react-native-paper": "5.8.0",
|
||||
"react-native-paper": "5.9.1",
|
||||
"react-native-popup-menu": "0.16.1",
|
||||
"react-native-quick-actions": "0.3.13",
|
||||
"react-native-reanimated": "3.3.0",
|
||||
"react-native-rsa-native": "2.0.5",
|
||||
"react-native-safe-area-context": "4.6.0",
|
||||
"react-native-safe-area-context": "4.6.4",
|
||||
"react-native-securerandom": "1.0.1",
|
||||
"react-native-share": "8.2.2",
|
||||
"react-native-side-menu-updated": "1.3.2",
|
||||
"react-native-sqlite-storage": "6.0.1",
|
||||
"react-native-url-polyfill": "1.3.0",
|
||||
"react-native-vector-icons": "9.2.0",
|
||||
@@ -75,7 +72,7 @@
|
||||
"react-native-vosk": "0.1.12",
|
||||
"react-native-webview": "12.4.0",
|
||||
"react-native-zip-archive": "6.0.9",
|
||||
"react-redux": "8.1.1",
|
||||
"react-redux": "8.1.2",
|
||||
"redux": "4.2.1",
|
||||
"rn-fetch-blob": "0.12.0",
|
||||
"stream": "0.0.2",
|
||||
@@ -105,15 +102,15 @@
|
||||
"@joplin/tools": "~2.12",
|
||||
"@lezer/highlight": "1.1.4",
|
||||
"@testing-library/jest-native": "5.4.2",
|
||||
"@testing-library/react-native": "12.1.2",
|
||||
"@testing-library/react-native": "12.1.3",
|
||||
"@tsconfig/react-native": "2.0.2",
|
||||
"@types/fs-extra": "11.0.1",
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/jest": "29.5.3",
|
||||
"@types/react": "18.0.24",
|
||||
"@types/react-native": "0.70.6",
|
||||
"@types/react-redux": "7.1.25",
|
||||
"@types/tar-stream": "2.2.2",
|
||||
"babel-jest": "29.2.1",
|
||||
"babel-jest": "29.5.0",
|
||||
"babel-plugin-module-resolver": "4.1.0",
|
||||
"execa": "4.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
@@ -127,10 +124,10 @@
|
||||
"nodemon": "2.0.22",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"sqlite3": "5.1.6",
|
||||
"ts-jest": "29.1.0",
|
||||
"ts-jest": "29.1.1",
|
||||
"ts-loader": "9.4.4",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "5.0.2",
|
||||
"typescript": "5.1.3",
|
||||
"uglify-js": "3.17.4",
|
||||
"webpack": "5.74.0"
|
||||
}
|
||||
|
||||
@@ -22,14 +22,14 @@ import handleShared from './utils/shareHandler';
|
||||
import uuid from '@joplin/lib/uuid';
|
||||
import { loadKeychainServiceAndSettings } from '@joplin/lib/services/SettingUtils';
|
||||
import KeychainServiceDriverMobile from '@joplin/lib/services/keychain/KeychainServiceDriver.mobile';
|
||||
import { setLocale } from '@joplin/lib/locale';
|
||||
import { _, setLocale } from '@joplin/lib/locale';
|
||||
import SyncTargetJoplinServer from '@joplin/lib/SyncTargetJoplinServer';
|
||||
import SyncTargetJoplinCloud from '@joplin/lib/SyncTargetJoplinCloud';
|
||||
import SyncTargetOneDrive from '@joplin/lib/SyncTargetOneDrive';
|
||||
import initProfile from '@joplin/lib/services/profileConfig/initProfile';
|
||||
const VersionInfo = require('react-native-version-info').default;
|
||||
const { Keyboard, BackHandler, View, StatusBar, Platform, Dimensions } = require('react-native');
|
||||
import { AppState as RNAppState, EmitterSubscription, Linking, NativeEventSubscription, Appearance } from 'react-native';
|
||||
const { Keyboard, BackHandler, Animated, View, StatusBar, Platform, Dimensions } = require('react-native');
|
||||
import { AppState as RNAppState, EmitterSubscription, Linking, NativeEventSubscription, Appearance, AccessibilityInfo } from 'react-native';
|
||||
import getResponsiveValue from './components/getResponsiveValue';
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
const DropdownAlert = require('react-native-dropdownalert').default;
|
||||
@@ -67,7 +67,7 @@ const { OneDriveLoginScreen } = require('./components/screens/onedrive-login.js'
|
||||
import EncryptionConfigScreen from './components/screens/encryption-config';
|
||||
const { DropboxLoginScreen } = require('./components/screens/dropbox-login.js');
|
||||
const { MenuContext } = require('react-native-popup-menu');
|
||||
import { Drawer } from 'react-native-drawer-layout';
|
||||
import SideMenu from './components/SideMenu';
|
||||
import SideMenuContent from './components/side-menu-content';
|
||||
const { SideMenuContentNote } = require('./components/side-menu-content-note.js');
|
||||
const { DatabaseDriverReactNative } = require('./utils/database-driver-react-native');
|
||||
@@ -85,6 +85,7 @@ const SyncTargetWebDAV = require('@joplin/lib/SyncTargetWebDAV.js');
|
||||
const SyncTargetDropbox = require('@joplin/lib/SyncTargetDropbox.js');
|
||||
const SyncTargetAmazonS3 = require('@joplin/lib/SyncTargetAmazonS3.js');
|
||||
import BiometricPopup from './components/biometrics/BiometricPopup';
|
||||
import initLib from '@joplin/lib/initLib';
|
||||
|
||||
SyncTargetRegistry.addClass(SyncTargetNone);
|
||||
SyncTargetRegistry.addClass(SyncTargetOneDrive);
|
||||
@@ -116,8 +117,8 @@ import ProfileEditor from './components/ProfileSwitcher/ProfileEditor';
|
||||
import sensorInfo, { SensorInfo } from './components/biometrics/sensorInfo';
|
||||
import { getCurrentProfile } from '@joplin/lib/services/profileConfig';
|
||||
import { getDatabaseName, getProfilesRootDir, getResourceDir, setDispatch } from './services/profiles';
|
||||
import { ReactNode } from 'react';
|
||||
import userFetcher, { initializeUserFetcher } from '@joplin/lib/utils/userFetcher';
|
||||
import { ReactNode } from 'react';
|
||||
import { parseShareCache } from '@joplin/lib/services/share/reducer';
|
||||
import autodetectTheme, { onSystemColorSchemeChange } from './utils/autodetectTheme';
|
||||
|
||||
@@ -474,6 +475,7 @@ async function initialize(dispatch: Function) {
|
||||
}
|
||||
|
||||
Logger.initializeGlobalLogger(mainLogger);
|
||||
initLib(mainLogger);
|
||||
|
||||
reg.setLogger(mainLogger);
|
||||
reg.setShowErrorMessageBoxHandler((message: string) => { alert(message); });
|
||||
@@ -746,6 +748,7 @@ class AppComponent extends React.Component {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
sideMenuContentOpacity: new Animated.Value(0),
|
||||
sideMenuWidth: this.getSideMenuWidth(),
|
||||
sensorInfo: null,
|
||||
};
|
||||
@@ -981,6 +984,9 @@ class AppComponent extends React.Component {
|
||||
this.props.dispatch({
|
||||
type: isOpen ? 'SIDE_MENU_OPEN' : 'SIDE_MENU_CLOSE',
|
||||
});
|
||||
AccessibilityInfo.announceForAccessibility(
|
||||
isOpen ? _('Side menu opened') : _('Side menu closed')
|
||||
);
|
||||
}
|
||||
|
||||
private getSideMenuWidth = () => {
|
||||
@@ -1039,20 +1045,18 @@ class AppComponent extends React.Component {
|
||||
|
||||
const mainContent = (
|
||||
<View style={{ flex: 1, backgroundColor: theme.backgroundColor }}>
|
||||
<Drawer
|
||||
// Need to reset the key here based on menu position, otherwise
|
||||
// the drawer will flash open on screen and close every time the
|
||||
// drawer position switches (i.e. when opening or closing a note)
|
||||
key={`main-drawer-${menuPosition}`}
|
||||
open={this.props.showSideMenu}
|
||||
onOpen={() => this.sideMenu_change(true)}
|
||||
onClose={() => this.sideMenu_change(false)}
|
||||
drawerPosition={menuPosition}
|
||||
swipeEdgeWidth={15}
|
||||
drawerStyle={{
|
||||
width: this.state.sideMenuWidth,
|
||||
<SideMenu
|
||||
menu={sideMenuContent}
|
||||
edgeHitWidth={20}
|
||||
openMenuOffset={this.state.sideMenuWidth}
|
||||
menuPosition={menuPosition}
|
||||
onChange={(isOpen: boolean) => this.sideMenu_change(isOpen)}
|
||||
onSliding={(percent: number) => {
|
||||
this.props.dispatch({
|
||||
type: 'SIDE_MENU_OPEN_PERCENT',
|
||||
value: percent,
|
||||
});
|
||||
}}
|
||||
renderDrawerContent={() => sideMenuContent}
|
||||
>
|
||||
<StatusBar barStyle={statusBarStyle} />
|
||||
<MenuContext style={{ flex: 1 }}>
|
||||
@@ -1069,7 +1073,7 @@ class AppComponent extends React.Component {
|
||||
/> }
|
||||
</SafeAreaView>
|
||||
</MenuContext>
|
||||
</Drawer>
|
||||
</SideMenu>
|
||||
</View>
|
||||
);
|
||||
|
||||
|
||||
@@ -351,7 +351,7 @@ export default class FsDriverRN extends FsDriverBase {
|
||||
} else {
|
||||
// the result is an array
|
||||
if (multiple) {
|
||||
result = await DocumentPicker.pickMultiple();
|
||||
result = await DocumentPicker.pick({ allowMultiSelection: true });
|
||||
} else {
|
||||
result = [await DocumentPicker.pick()];
|
||||
}
|
||||
|
||||
@@ -45,16 +45,16 @@
|
||||
"entities": "2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/node": "18.15.13",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.0",
|
||||
"@typescript-eslint/parser": "5.59.0",
|
||||
"@types/jest": "29.5.3",
|
||||
"@types/node": "18.16.18",
|
||||
"@typescript-eslint/eslint-plugin": "5.60.0",
|
||||
"@typescript-eslint/parser": "5.60.0",
|
||||
"coveralls": "3.1.1",
|
||||
"eslint": "8.39.0",
|
||||
"eslint": "8.43.0",
|
||||
"jest": "29.5.0",
|
||||
"prettier": "2.8.8",
|
||||
"ts-jest": "29.1.0",
|
||||
"typescript": "5.0.2"
|
||||
"ts-jest": "29.1.1",
|
||||
"typescript": "5.1.3"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "ts-jest",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"standard": "17.1.0",
|
||||
"tap": "16.3.7"
|
||||
"tap": "16.3.8"
|
||||
},
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "generate-plugin-doc",
|
||||
"packageManager": "yarn@3.3.1",
|
||||
"packageManager": "yarn@3.6.0",
|
||||
"scripts": {
|
||||
"buildPluginDoc_": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme '../../Assets/PluginDocTheme/' --readme '../../Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out ../../../joplin-website/docs/api/references/plugin_api ../lib/services/plugins/api/"
|
||||
},
|
||||
|
||||
@@ -59,7 +59,6 @@ import Resource from './models/Resource';
|
||||
import { ProfileConfig } from './services/profileConfig/types';
|
||||
import initProfile from './services/profileConfig/initProfile';
|
||||
import { parseShareCache } from './services/share/reducer';
|
||||
|
||||
import RotatingLogs from './RotatingLogs';
|
||||
|
||||
const appLogger: LoggerWrapper = Logger.create('App');
|
||||
@@ -69,6 +68,7 @@ const appLogger: LoggerWrapper = Logger.create('App');
|
||||
|
||||
interface StartOptions {
|
||||
keychainEnabled?: boolean;
|
||||
setupGlobalLogger?: boolean;
|
||||
}
|
||||
|
||||
export default class BaseApplication {
|
||||
@@ -547,7 +547,7 @@ export default class BaseApplication {
|
||||
const newState = store.getState();
|
||||
|
||||
if (this.hasGui() && ['NOTE_UPDATE_ONE', 'NOTE_DELETE', 'FOLDER_UPDATE_ONE', 'FOLDER_DELETE'].indexOf(action.type) >= 0) {
|
||||
if (!(await reg.syncTarget().syncStarted())) void reg.scheduleSync(1000, { syncSteps: ['update_remote', 'delete_remote'] });
|
||||
if (!(await reg.syncTarget().syncStarted())) void reg.scheduleSync(15 * 1000, { syncSteps: ['update_remote', 'delete_remote'] });
|
||||
SearchEngine.instance().scheduleSyncTables();
|
||||
}
|
||||
|
||||
@@ -735,9 +735,24 @@ export default class BaseApplication {
|
||||
return toSystemSlashes(output, 'linux');
|
||||
}
|
||||
|
||||
protected startRotatingLogMaintenance(profileDir: string) {
|
||||
this.rotatingLogs = new RotatingLogs(profileDir);
|
||||
const processLogs = async () => {
|
||||
try {
|
||||
await this.rotatingLogs.cleanActiveLogFile();
|
||||
await this.rotatingLogs.deleteNonActiveLogFiles();
|
||||
} catch (error) {
|
||||
appLogger.error(error);
|
||||
}
|
||||
};
|
||||
shim.setTimeout(() => { void processLogs(); }, 60000);
|
||||
shim.setInterval(() => { void processLogs(); }, 24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
public async start(argv: string[], options: StartOptions = null): Promise<any> {
|
||||
options = {
|
||||
keychainEnabled: true,
|
||||
setupGlobalLogger: true,
|
||||
...options,
|
||||
};
|
||||
|
||||
@@ -800,18 +815,15 @@ export default class BaseApplication {
|
||||
const extraFlags = await this.readFlagsFromFile(`${profileDir}/flags.txt`);
|
||||
initArgs = { ...initArgs, ...extraFlags };
|
||||
|
||||
const globalLogger = Logger.globalLogger;
|
||||
|
||||
|
||||
|
||||
const globalLogger = new Logger();
|
||||
globalLogger.addTarget(TargetType.File, { path: `${profileDir}/log.txt` });
|
||||
if (Setting.value('appType') === 'desktop') {
|
||||
globalLogger.addTarget(TargetType.Console);
|
||||
if (options.setupGlobalLogger) {
|
||||
globalLogger.addTarget(TargetType.File, { path: `${profileDir}/log.txt` });
|
||||
if (Setting.value('appType') === 'desktop') {
|
||||
globalLogger.addTarget(TargetType.Console);
|
||||
}
|
||||
globalLogger.setLevel(initArgs.logLevel);
|
||||
}
|
||||
globalLogger.setLevel(initArgs.logLevel);
|
||||
Logger.initializeGlobalLogger(globalLogger);
|
||||
|
||||
|
||||
|
||||
reg.setLogger(Logger.create('') as Logger);
|
||||
// reg.dispatch = () => {};
|
||||
@@ -934,18 +946,6 @@ export default class BaseApplication {
|
||||
|
||||
await MigrationService.instance().run();
|
||||
|
||||
this.rotatingLogs = new RotatingLogs(profileDir);
|
||||
const processLogs = async () => {
|
||||
try {
|
||||
await this.rotatingLogs.cleanActiveLogFile();
|
||||
await this.rotatingLogs.deleteNonActiveLogFiles();
|
||||
} catch (error) {
|
||||
appLogger.error(error);
|
||||
}
|
||||
};
|
||||
shim.setTimeout(() => { void processLogs(); }, 60000);
|
||||
shim.setInterval(() => { void processLogs(); }, 24 * 60 * 60 * 1000);
|
||||
|
||||
return argv;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,12 @@ export default class BaseSyncTarget {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if the sync target expects a non-empty sync.{id}.password
|
||||
// setting.
|
||||
public static requiresPassword() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static description(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ export default class ClipperServer {
|
||||
} catch (error) {
|
||||
this.setStartState(StartState.Idle);
|
||||
this.logger().error(error);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
this.server_ = require('http').createServer();
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const shim_1 = require("./shim");
|
||||
class RotatingLogs {
|
||||
constructor(logFilesDir, maxFileSize = null, inactiveMaxAge = null) {
|
||||
this.maxFileSize = 1024 * 1024 * 100;
|
||||
this.inactiveMaxAge = 90 * 24 * 60 * 60 * 1000;
|
||||
this.logFilesDir = logFilesDir;
|
||||
if (maxFileSize)
|
||||
this.maxFileSize = maxFileSize;
|
||||
if (inactiveMaxAge)
|
||||
this.inactiveMaxAge = inactiveMaxAge;
|
||||
}
|
||||
cleanActiveLogFile() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const stats = yield this.fsDriver().stat(this.logFileFullpath());
|
||||
if (stats.size >= this.maxFileSize) {
|
||||
const newLogFile = this.logFileFullpath(this.getNameToNonActiveLogFile());
|
||||
yield this.fsDriver().move(this.logFileFullpath(), newLogFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
getNameToNonActiveLogFile() {
|
||||
return `log-${Date.now()}.txt`;
|
||||
}
|
||||
deleteNonActiveLogFiles() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const files = yield this.fsDriver().readDirStats(this.logFilesDir);
|
||||
for (const file of files) {
|
||||
if (!file.path.match(/^log-[0-9]+.txt$/gi))
|
||||
continue;
|
||||
const ageOfTheFile = Date.now() - file.birthtime;
|
||||
if (ageOfTheFile >= this.inactiveMaxAge) {
|
||||
yield this.fsDriver().remove(this.logFileFullpath(file.path));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
logFileFullpath(fileName = 'log.txt') {
|
||||
return `${this.logFilesDir}/${fileName}`;
|
||||
}
|
||||
fsDriver() {
|
||||
return shim_1.default.fsDriver();
|
||||
}
|
||||
}
|
||||
exports.default = RotatingLogs;
|
||||
//# sourceMappingURL=RotatingLogs.js.map
|
||||
@@ -1,56 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const test_utils_1 = require("./testing/test-utils");
|
||||
const RotatingLogs_1 = require("./RotatingLogs");
|
||||
const createTestLogFile = (dir) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
yield (0, fs_extra_1.writeFile)(`${dir}/log.txt`, 'some content');
|
||||
});
|
||||
describe('RotatingLogs', () => {
|
||||
test('should rename log.txt to log-TIMESTAMP.txt', () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
let dir;
|
||||
try {
|
||||
dir = yield (0, test_utils_1.createTempDir)();
|
||||
yield createTestLogFile(dir);
|
||||
let files = yield (0, fs_extra_1.readdir)(dir);
|
||||
expect(files.find(file => file.match(/^log.txt$/gi))).toBeTruthy();
|
||||
expect(files.length).toBe(1);
|
||||
const rotatingLogs = new RotatingLogs_1.default(dir, 1, 1);
|
||||
yield rotatingLogs.cleanActiveLogFile();
|
||||
files = yield (0, fs_extra_1.readdir)(dir);
|
||||
expect(files.find(file => file.match(/^log.txt$/gi))).toBeFalsy();
|
||||
expect(files.find(file => file.match(/^log-[0-9]+.txt$/gi))).toBeTruthy();
|
||||
expect(files.length).toBe(1);
|
||||
}
|
||||
finally {
|
||||
yield (0, fs_extra_1.remove)(dir);
|
||||
}
|
||||
}));
|
||||
test('should delete inative log file after 1ms', () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
let dir;
|
||||
try {
|
||||
dir = yield (0, test_utils_1.createTempDir)();
|
||||
yield createTestLogFile(dir);
|
||||
const rotatingLogs = new RotatingLogs_1.default(dir, 1, 1);
|
||||
yield rotatingLogs.cleanActiveLogFile();
|
||||
yield (0, test_utils_1.msleep)(1);
|
||||
yield rotatingLogs.deleteNonActiveLogFiles();
|
||||
const files = yield (0, fs_extra_1.readdir)(dir);
|
||||
expect(files.find(file => file.match(/^log-[0-9]+.txt$/gi))).toBeFalsy();
|
||||
expect(files.length).toBe(0);
|
||||
}
|
||||
finally {
|
||||
yield (0, fs_extra_1.remove)(dir);
|
||||
}
|
||||
}));
|
||||
});
|
||||
//# sourceMappingURL=RotatingLogs.test.js.map
|
||||
@@ -12,7 +12,7 @@ describe('RotatingLogs', () => {
|
||||
try {
|
||||
dir = await createTempDir();
|
||||
await createTestLogFile(dir);
|
||||
let files: string[] = await readdir(dir);
|
||||
let files = await readdir(dir);
|
||||
expect(files.find(file => file.match(/^log.txt$/gi))).toBeTruthy();
|
||||
expect(files.length).toBe(1);
|
||||
const rotatingLogs: RotatingLogs = new RotatingLogs(dir, 1, 1);
|
||||
@@ -26,7 +26,7 @@ describe('RotatingLogs', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('should delete inative log file after 1ms', async () => {
|
||||
test('should delete inactive log file after 1ms', async () => {
|
||||
let dir: string;
|
||||
try {
|
||||
dir = await createTempDir();
|
||||
@@ -42,4 +42,21 @@ describe('RotatingLogs', () => {
|
||||
await remove(dir);
|
||||
}
|
||||
});
|
||||
|
||||
test('should not delete the log-timestamp.txt right after its be created', async () => {
|
||||
let dir: string;
|
||||
try {
|
||||
dir = await createTempDir();
|
||||
await createTestLogFile(dir);
|
||||
await msleep(100);
|
||||
const rotatingLogs: RotatingLogs = new RotatingLogs(dir, 1, 100);
|
||||
await rotatingLogs.cleanActiveLogFile();
|
||||
await rotatingLogs.deleteNonActiveLogFiles();
|
||||
const files = await readdir(dir);
|
||||
expect(files.find(file => file.match(/^log-[0-9]+.txt$/gi))).toBeTruthy();
|
||||
expect(files.length).toBe(1);
|
||||
} finally {
|
||||
await remove(dir);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,7 +29,8 @@ export default class RotatingLogs {
|
||||
const files: Stat[] = await this.fsDriver().readDirStats(this.logFilesDir);
|
||||
for (const file of files) {
|
||||
if (!file.path.match(/^log-[0-9]+.txt$/gi)) continue;
|
||||
const ageOfTheFile: number = Date.now() - file.birthtime;
|
||||
const timestamp: number = parseInt(file.path.match(/[0-9]+/g)[0], 10);
|
||||
const ageOfTheFile: number = Date.now() - timestamp;
|
||||
if (ageOfTheFile >= this.inactiveMaxAge) {
|
||||
await this.fsDriver().remove(this.logFileFullpath(file.path));
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ class SyncTargetAmazonS3 extends BaseSyncTarget {
|
||||
return true;
|
||||
}
|
||||
|
||||
static requiresPassword() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static s3BucketName() {
|
||||
return Setting.value('sync.8.path');
|
||||
}
|
||||
|
||||
@@ -49,6 +49,10 @@ export default class SyncTargetJoplinCloud extends BaseSyncTarget {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static requiresPassword() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public async fileApi(): Promise<FileApi> {
|
||||
return super.fileApi();
|
||||
}
|
||||
|
||||
@@ -65,6 +65,10 @@ export default class SyncTargetJoplinServer extends BaseSyncTarget {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static requiresPassword() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public async fileApi(): Promise<FileApi> {
|
||||
return super.fileApi();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ class SyncTargetNextcloud extends BaseSyncTarget {
|
||||
return true;
|
||||
}
|
||||
|
||||
static requiresPassword() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static async checkConfig(options) {
|
||||
return SyncTargetWebDAV.checkConfig(options);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@ class SyncTargetWebDAV extends BaseSyncTarget {
|
||||
return true;
|
||||
}
|
||||
|
||||
static requiresPassword() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static async newFileApi_(syncTargetId, options) {
|
||||
const apiOptions = {
|
||||
baseUrl: () => options.path(),
|
||||
|
||||
@@ -272,7 +272,7 @@ export default class Synchronizer {
|
||||
}
|
||||
|
||||
public async cancel() {
|
||||
if (this.cancelling_ || this.state() === 'idle') return;
|
||||
if (this.cancelling_ || this.state() === 'idle') return null;
|
||||
|
||||
// Stop queue but don't set it to null as it may be used to
|
||||
// retrieve the last few downloads.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const Setting = require('../../models/Setting').default;
|
||||
const SyncTargetRegistry = require('../../SyncTargetRegistry').default;
|
||||
const ObjectUtils = require('../../ObjectUtils');
|
||||
const { _ } = require('../../locale');
|
||||
const Setting = require('../../../models/Setting').default;
|
||||
const SyncTargetRegistry = require('../../../SyncTargetRegistry').default;
|
||||
const ObjectUtils = require('../../../ObjectUtils');
|
||||
const { _ } = require('../../../locale');
|
||||
const { createSelector } = require('reselect');
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import SyncTargetRegistry from '../../../SyncTargetRegistry';
|
||||
import shouldShowMissingPasswordWarning from './shouldShowMissingPasswordWarning';
|
||||
|
||||
// Maps targets to whether each target requires a password.
|
||||
// A subset of all sync targets.
|
||||
const targetToRequiresPassword: Record<string, boolean> = {
|
||||
'nextcloud': true,
|
||||
'webdav': true,
|
||||
'amazon_s3': true,
|
||||
'joplinServer': true,
|
||||
'joplinCloud': true,
|
||||
'onedrive': false,
|
||||
'dropbox': false,
|
||||
};
|
||||
|
||||
describe('shouldShowMissingPasswordWarning', () => {
|
||||
it('should return true when sync target requires a password and the password is missing', () => {
|
||||
for (const targetName in targetToRequiresPassword) {
|
||||
const targetId = SyncTargetRegistry.nameToId(targetName);
|
||||
const expected = targetToRequiresPassword[targetName];
|
||||
|
||||
expect(shouldShowMissingPasswordWarning(targetId, {})).toBe(expected);
|
||||
|
||||
// Should also consider an empty string to be missing
|
||||
const settings = {
|
||||
[`sync.${targetId}.password`]: '',
|
||||
};
|
||||
expect(shouldShowMissingPasswordWarning(targetId, settings)).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
it('should return false when a password is present', () => {
|
||||
for (const targetName in targetToRequiresPassword) {
|
||||
const targetId = SyncTargetRegistry.nameToId(targetName);
|
||||
const settings = {
|
||||
[`sync.${targetId}.password`]: 'some nonempty',
|
||||
};
|
||||
|
||||
expect(shouldShowMissingPasswordWarning(targetId, settings)).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import SyncTargetRegistry from '../../../SyncTargetRegistry';
|
||||
|
||||
const shouldShowMissingPasswordWarning = (syncTargetId: number, settings: any) => {
|
||||
const syncTargetClass = SyncTargetRegistry.classById(syncTargetId);
|
||||
|
||||
return syncTargetClass.requiresPassword() && !settings[`sync.${syncTargetId}.password`];
|
||||
};
|
||||
|
||||
export default shouldShowMissingPasswordWarning;
|
||||
9
packages/lib/initLib.ts
Normal file
9
packages/lib/initLib.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
// @joplin/lib has its own copy of the Logger class, however we want it to be
|
||||
// initialised with the same logger instance as the calling application, so that
|
||||
// the lib and app share the same log. This initLib() function is used for this
|
||||
// and must be called by any "app" package that makes use of the lib package.
|
||||
export default (globalLogger: Logger) => {
|
||||
Logger.initializeGlobalLogger(globalLogger);
|
||||
};
|
||||
@@ -76,7 +76,7 @@
|
||||
"Application": "Anwendung",
|
||||
"Apply": "Anwenden",
|
||||
"Are you sure you want to renew the authorisation token?": "Bist du sicher, dass du den Berechtigungstoken erneuern möchtest?",
|
||||
"Are you sure you want to return to the default layout? The current layout configuration will be lost.": "Sicher, dass du zum Standardlayout zurückkehren möchtest? Das aktuelle Layout geht dabei verloren",
|
||||
"Are you sure you want to return to the default layout? The current layout configuration will be lost.": "Sicher, dass du zum Standardlayout zurückkehren möchtest? Das aktuelle Layout geht dabei verloren.",
|
||||
"Arguments:": "Kommandozeilenargumente:",
|
||||
"Aritim Dark": "Aritim dunkel",
|
||||
"Attach": "Anhängen",
|
||||
@@ -99,6 +99,7 @@
|
||||
"Automatically switch theme to match system theme": "Automatisch das Design ändern, um es dem System-Design anzupassen",
|
||||
"Back": "Zurück",
|
||||
"Basic": "Standard",
|
||||
"Biometric unlock is not setup on the device. Please set it up in order to unlock Joplin. If the device is on lockout, consider switching it off and on to reset biometrics scanning.": "Biometrisches Entsperren ist auf diesem Gerät nicht eingerichtet. Bitte richte es ein, um Joplin zu entsperren. Falls das Gerät gesperrt ist, solltest du es aus- und wieder einschalten, um das biometrische Scannen zurückzusetzen.",
|
||||
"Bold": "Fett",
|
||||
"Browse all plugins": "Alle Erweiterungen durchsuchen",
|
||||
"Browse...": "Durchsuchen ...",
|
||||
@@ -169,6 +170,7 @@
|
||||
"Continue": "Fortfahren",
|
||||
"Convert to note": "In eine Notiz umwandeln",
|
||||
"Convert to todo": "In eine Aufgabe umwandeln",
|
||||
"Converting speech to text...": "Wandle Sprache in Text um...",
|
||||
"Copy": "Kopieren",
|
||||
"Copy dev mode command to clipboard": "Entwicklermodus-Befehl in Zwischenablage kopieren",
|
||||
"Copy external link": "Externen Link kopieren",
|
||||
@@ -187,6 +189,7 @@
|
||||
"Could not switch profile: %s": "Konnte das Profil nicht wechseln: %s",
|
||||
"Could not upgrade master key: %s": "Konnte Hauptschlüssel nicht aktualisieren: %s",
|
||||
"Could not verify the share status of this notebook - aborting. Please try again when you are connected to the internet.": "Der Freigabestatus dieses Notizbuchs konnte nicht überprüft werden - Vorgang wird abgebrochen. Bitte versuche es erneut, wenn eine Internetverbindung besteht.",
|
||||
"Could not verify your identify: %s": "Konnte deine Identität nicht verifizieren: %s",
|
||||
"Create": "Erstellen",
|
||||
"Create a new notebook under a parent notebook.": "Erstelle ein neues Notizbuch unter einem übergeordneten Notizbuch.",
|
||||
"Create a notebook": "Notizbuch erstellen",
|
||||
@@ -277,6 +280,7 @@
|
||||
"Downloaded and decrypted": "Heruntergeladen und entschlüsselt",
|
||||
"Downloaded and encrypted": "Heruntergeladen und verschlüsselt",
|
||||
"Downloading": "Wird heruntergeladen",
|
||||
"Downloading %s language files...": "Lade %s Sprachdateien herunter...",
|
||||
"Downloading resources...": "Anhänge werden heruntergeladen ...",
|
||||
"Dracula": "Dracula",
|
||||
"Drop notes or files here": "Notizen oder Dateien hierher ziehen",
|
||||
@@ -326,6 +330,7 @@
|
||||
"Enable soft breaks": "Weiche Zeilenumbrüche aktivieren",
|
||||
"Enable spellcheck in the text editor": "Aktiviere die Rechtschreibprüfung im Text-Editor",
|
||||
"Enable table of contents extension": "Inhaltsverzeichnis-Erweiterung aktivieren",
|
||||
"Enable the Markdown toolbar": "Markdown Werkzeugleiste aktivieren",
|
||||
"Enable typographer support": "Typographie-Unterstützung aktivieren",
|
||||
"Enable video player": "Videospieler aktivieren",
|
||||
"Enable Web Clipper Service": "Web-Clipper-Dienst aktivieren",
|
||||
@@ -406,6 +411,7 @@
|
||||
"Headers": "Kopfzeilen",
|
||||
"Heading": "Überschrift",
|
||||
"Help": "Hilfe",
|
||||
"Hermes enabled: %d": "Hermes aktiviert: %d",
|
||||
"Hide %s": "%s ausblenden",
|
||||
"Hide advanced": "Erweitertes verstecken",
|
||||
"Hide disabled": "Deaktiviertes verstecken",
|
||||
@@ -489,6 +495,7 @@
|
||||
"Later": "Später",
|
||||
"Layout": "Layout",
|
||||
"Layout button sequence": "Layout-Reihenfolge",
|
||||
"Leave it blank to download the language files from the default website": "Lasse es leer, um die Sprachdateien von der Standardseite herunterzuladen.",
|
||||
"Leave notebook...": "Verlasse Notizbuch...",
|
||||
"Legal": "Legal",
|
||||
"Letter": "Letter",
|
||||
@@ -502,6 +509,7 @@
|
||||
"List item": "Listeneintrag",
|
||||
"Lists": "Listen",
|
||||
"Loaded": "Geladen",
|
||||
"Loading...": "Lade...",
|
||||
"Location": "Standort",
|
||||
"Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at \"%s\" and resume the operation.": "Eine Sperrdatei ist vorhanden. Wenn du dir sicher bist, dass keine Synchronisation im Gange ist, kannst du die Sperrdatei „%s“ löschen und den Vorgang fortsetzen.",
|
||||
"Log": "Protokoll",
|
||||
@@ -642,6 +650,7 @@
|
||||
"Please enter your password in the master key list below before upgrading the key.": "Bitte gib zuerst dein Passwort in der unten stehenden Liste der Hauptschlüssel ein, bevor du den Schlüssel aktualisierst.",
|
||||
"Please note that if it is a large notebook, it may take a few minutes for all the notes to show up on the recipient's device.": "Wenn das Notizbuch sehr groß ist, kann es ein paar Minuten dauern, bis alle Notizen auf dem Empfängergerät erscheinen.",
|
||||
"Please open the following URL in your browser to authenticate the application. The application will create a directory in \"Apps/Joplin\" and will only read and write files in this directory. It will have no access to any files outside this directory nor to any other personal data. No data will be shared with any third party.": "Bitte öffne die folgende URL in deinem Browser, um die Anwendung zu authentifizieren. Die Anwendung erstellt ein Verzeichnis in „Apps/Joplin“ und kann nur Dateien in diesem Verzeichnis lesen und schreiben. Sie hat weder Zugriff auf Dateien außerhalb dieses Verzeichnisses noch auf andere persönliche Daten. Es werden keine Daten an Dritte weitergegeben.",
|
||||
"Please record your voice...": "Bitte nehme deine Stimme auf...",
|
||||
"Please select a notebook first.": "Bitte wähle erst ein Notizbuch aus.",
|
||||
"Please select the note or notebook to be deleted first.": "Bitte wähle zuerst eine Notiz oder ein Notizbuch aus, das gelöscht werden soll.",
|
||||
"Please select where the sync status should be exported to": "Bitte wähle aus, wohin der Synchronisations-Status exportiert werden soll",
|
||||
@@ -751,6 +760,7 @@
|
||||
"Select all": "Alles auswählen",
|
||||
"Select emoji...": "Emoji auswählen...",
|
||||
"Select file...": "Datei auswählen...",
|
||||
"Select parent notebook": "Eltern-Notizbuch auswählen",
|
||||
"Server is already running on port %d": "Server läuft bereits auf Port %d",
|
||||
"Server is not running.": "Server läuft nicht.",
|
||||
"Server is running on port %d": "Server läuft auf Port %d",
|
||||
@@ -996,6 +1006,8 @@
|
||||
"View them now": "Zeige sie jetzt an",
|
||||
"Viewer": "Vorschau",
|
||||
"Vim": "Vim",
|
||||
"Voice typing language files (URL)": "Sprachdateien für die Spracheingabe (URL)",
|
||||
"Voice typing...": "Spracheingabe...",
|
||||
"Warning": "Warnung",
|
||||
"Warning: not all resources shown for performance reasons (limit: %s).": "Warnung: Aus Leistungsgründen werden nicht alle Anhänge angezeigt (Obergrenze: %s).",
|
||||
"Web Clipper": "Web Clipper",
|
||||
@@ -1005,6 +1017,7 @@
|
||||
"WebDAV username": "WebDAV-Benutzername",
|
||||
"Website and documentation": "Webseite und Dokumentation",
|
||||
"Welcome to Joplin!\n\nType `:help shortcuts` for the list of keyboard shortcuts, or just `:help` for usage information.\n\nFor example, to create a notebook press `mb`; to create a note press `mn`.": "Willkommen bei Joplin!\n\nTippe `:help shortcuts` für eine Liste der Shortcuts oder `:help` für Informationen zur Benutzung ein.\n\nUm zum Beispiel ein Notizbuch zu erstellen, drücke `mb`; um eine Notiz zu erstellen drücke `mn`.",
|
||||
"Welcome!": "Willkommen!",
|
||||
"When creating a new note:": "Wenn eine neue Notiz erstellt wird:",
|
||||
"When creating a new to-do:": "Wenn eine neue Aufgabe erstellt wird:",
|
||||
"Words": "Wörter",
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"\"%s\" is missing the required \"%s\" property.": "Το \"%s\" δεν διαθέτει την απαιτούμενη ιδιότητα \"%s\".",
|
||||
"%d days": "%d ημέρες",
|
||||
"%d GB": "%d GB",
|
||||
"%d GB storage space": "%d GB αποθηκευτικού χώρου",
|
||||
"%d hour": "%d ώρα",
|
||||
"%d hours": "%d ώρες",
|
||||
"%d MB": "%d MB",
|
||||
"%d MB per note or attachment": "%d MB ανά σημείωση ή συνημμένο",
|
||||
"%d minutes": "%d΄λεπτά",
|
||||
"%d notes match this pattern. Delete them?": "%d σημειώσεις ταιριάζουν. Θέλετε να διαγραφούν;",
|
||||
"%s": "%s",
|
||||
"%s %s (%s, %s)": "%s %s (%s, %s)",
|
||||
"%s (%s) could not be uploaded: %s": "%s (%s) δεν μπορούν να ανέβουν: %s",
|
||||
"%s (%s) would like to share a notebook with you.": "%s (%s) θα ήθελε να μοιραστεί μαζί σας ένα σημειωματάριο.",
|
||||
@@ -27,6 +32,7 @@
|
||||
"&Tools": "&Εργαλεία",
|
||||
"&View": "&Εμφάνιση",
|
||||
"(%s)": "(%s)",
|
||||
"(In plugin: %s)": "(Στο plugin: %s)",
|
||||
"(None)": "(Κανένας)",
|
||||
"(wysiwyg: %s)": "(wysiwyg: %s)",
|
||||
"- Camera: to allow taking a picture and attaching it to a note.": "- Φωτογραφική μηχανή: για να μπορείτε να τραβήξετε μια φωτογραφία και να την προσαρτήσετε σε μια σημείωση.",
|
||||
@@ -42,11 +48,13 @@
|
||||
"Accelerator \"%s\" is not valid.": "Ο επιταχυντής \"%s\" δεν είναι έγκυρος.",
|
||||
"Accelerator \"%s\" is used for \"%s\" and \"%s\" commands. This may lead to unexpected behaviour.": "Ο επιταχυντής \"%s\" χρησιμοποιείται για εντολές \"%s\" και \"%s\". Αυτό μπορεί να οδηγήσει σε απροσδόκητη συμπεριφορά.",
|
||||
"Accept": "Αποδοχή",
|
||||
"Account": "Λογαριασμός",
|
||||
"Action": "Ενέργεια",
|
||||
"Actions": "Ενέργειες",
|
||||
"Active": "Ενεργό",
|
||||
"Actual Size": "Πραγματικό μέγεθος",
|
||||
"Add body": "Προσθήκη σώματος κειμένου",
|
||||
"Add new": "Προσθήκη νέου",
|
||||
"Add or remove tags:": "Προσθήκη ή διαγραφή ετικετών:",
|
||||
"Add recipient:": "Προσθήκη παραλήπτη:",
|
||||
"Add title": "Προσθήκη τίτλου",
|
||||
@@ -55,17 +63,23 @@
|
||||
"Admin dashboard": "Πίνακας ελέγχου διαχειριστή",
|
||||
"Advanced options": "Επιλογές για προχωρημένους",
|
||||
"Advanced tools": "Προηγμένα εργαλεία",
|
||||
"All data, including notes, notebooks and tags will be permanently deleted.": "Όλα τα δεδομένα, συμπεριλαμβανομένων των σημειώσεων, των σημειωματάριων και των ετικετών, θα διαγραφούν οριστικά.",
|
||||
"All notes": "Όλες οι σημειώσεις",
|
||||
"All potential ports are in use - please report the issue at %s": "Όλες οι πιθανές θύρες χρησιμοποιούνται - αναφέρετε το ζήτημα στο %s",
|
||||
"Also displays unset and hidden config variables.": "Εμφανίζει επίσης μη ορισμένες και κρυφές μεταβλητές.",
|
||||
"Also publish linked notes": "Δημοσίευση σημειώσεων στο διαδίκτυο",
|
||||
"Always": "Πάντα",
|
||||
"Ambiguous notebook \"%s\". Please use notebook id instead - press \"ti\" to see the short notebook id or use $b for current selected notebook": "Διφορούμενο σημειωματάριο \"%s\". Παρακαλούμε χρησιμοποιήστε το id του σημειωματάριου - πατήστε \"ti\" για να δείτε το σύντομο id του σημειωματάριου ή χρησιμοποιήστε $b για το τρέχον επιλεγμένο σημειωματάριο.",
|
||||
"Ambiguous notebook \"%s\". Please use short notebook id instead - press \"ti\" to see the short notebook id": "Διφορούμενο σημειωματάριο \"%s\". Παρακαλούμε χρησιμοποιήστε το σύντομο αναγνωριστικό σημειωματάριου - πατήστε \"ti\" για να δείτε το σύντομο αναγνωριστικό σημειωματάριου",
|
||||
"An update is available, do you want to download it now?": "Υπάρχει διαθέσιμη μια ενημέρωση, θέλετε να την κατεβάσετε τώρα;",
|
||||
"Appearance": "Εμφάνιση",
|
||||
"Application": "Εφαρμογή",
|
||||
"Apply": "Εφαρμογή",
|
||||
"Are you sure you want to renew the authorisation token?": "Είστε βέβαιοι ότι θέλετε να ανανεώσετε το διακριτικό εξουσιοδότησης;",
|
||||
"Are you sure you want to return to the default layout? The current layout configuration will be lost.": "Είστε σίγουροι ότι θέλετε να επιστρέψετε στην προεπιλεγμένη διάταξη; Η τρέχουσα διαμόρφωση της διάταξης θα χαθεί.",
|
||||
"Arguments:": "Παράμετροι:",
|
||||
"Aritim Dark": "Aritim Dark",
|
||||
"Attach": "Επισύναψη",
|
||||
"Attach file": "Επισύναψη αρχείου",
|
||||
"Attach photo": "Επισυνάψτε μία φωτογραφία",
|
||||
"Attach...": "Επισύναψη...",
|
||||
@@ -84,10 +98,13 @@
|
||||
"Automatically check for updates": "Αυτόματος έλεγχος για ενημερώσεις",
|
||||
"Automatically switch theme to match system theme": "Αυτόματη εναλλαγή θέματος ώστε να ταιριάζει με το θέμα συστήματος",
|
||||
"Back": "Πίσω",
|
||||
"Basic": "Βασικό",
|
||||
"Biometric unlock is not setup on the device. Please set it up in order to unlock Joplin. If the device is on lockout, consider switching it off and on to reset biometrics scanning.": "Το βιομετρικό ξεκλείδωμα δεν έχει ρυθμιστεί στη συσκευή. Παρακαλούμε ρυθμίστε το για να ξεκλειδώσετε το Joplin. Εάν η συσκευή είναι κλειδωμένη, σκεφτείτε να την απενεργοποιήσετε και να την ενεργοποιήσετε για να επαναφέρετε τη βιομετρική σάρωση.",
|
||||
"Bold": "Έντονη γραφή",
|
||||
"Browse all plugins": "Αναζήτηση όλων των plugin",
|
||||
"Browse...": "Αναζήτηση...",
|
||||
"Bulleted List": "Λίστα με κουκκίδες",
|
||||
"Can Share": "Μπορεί να μοιραστεί",
|
||||
"Cancel": "Άκυρο",
|
||||
"Cancelling background synchronisation... Please wait.": "Ακύρωση συγχρονισμού ... Παρακαλώ περιμένετε.",
|
||||
"Cancelling...": "Ακύρωση...",
|
||||
@@ -96,6 +113,7 @@
|
||||
"Cannot change encrypted item": "Δεν είναι δυνατή η αλλαγή κρυπτογραφημένου στοιχείου",
|
||||
"Cannot copy note to \"%s\" notebook": "Δεν είναι δυνατή η αντιγραφή της σημείωσης στο σημειωματάριο \"%s\"",
|
||||
"Cannot find \"%s\".": "Δεν είναι δυνατή η εύρεση του \"%s\".",
|
||||
"Cannot find: \"%s\"": "Δεν είναι δυνατή η εύρεση του: \"%s\".",
|
||||
"Cannot initialise synchroniser.": "Δεν είναι δυνατή η προετοιμασία του συγχρονιστή.",
|
||||
"Cannot load \"%s\" module for format \"%s\" and output \"%s\"": "Δεν είναι δυνατή η φόρτωση του \"%s\" module με μορφή \"%s\" και έξοδο \"%s\"",
|
||||
"Cannot load \"%s\" module for format \"%s\" and target \"%s\"": "Δεν είναι δυνατή η φόρτωση του module \"%s\" για τη μορφοποίηση σε \"%s\" και την εξαγωγή σε \"%s\"",
|
||||
@@ -105,6 +123,7 @@
|
||||
"Cannot save %s \"%s\" because it is larger than the allowed limit (%s)": "Δεν είναι δυνατή η αποθήκευση του %s \"%s\" επειδή είναι μεγαλύτερο από το επιτρεπόμενο όριο (%s)",
|
||||
"Cannot save %s \"%s\" because it would go over the total allowed size (%s) for this account": "Δεν είναι δυνατή η αποθήκευση του %s \"%s\" επειδή υπερβαίνει το συνολικό επιτρεπόμενο μέγεθος (%s) για αυτόν τον λογαριασμό",
|
||||
"Cannot share encrypted notebook with recipient %s because they have not enabled end-to-end encryption. They may do so from the screen Configuration > Encryption.": "Δεν είναι δυνατή η κοινή χρήση κρυπτογραφημένου σημειωματάριου με τον παραλήπτη %s επειδή δεν έχει ενεργοποιήσει την κρυπτογράφηση από άκρο σε άκρο. Μπορούν να το κάνουν από την οθόνη Διαμόρφωση > Κρυπτογράφηση.",
|
||||
"Case sensitive": "Case sensitive",
|
||||
"Change application layout": "Αλλαγή διάταξης εφαρμογής",
|
||||
"Change language": "Αλλαγή γλώσσας",
|
||||
"Characters": "Χαρακτήρες",
|
||||
@@ -122,11 +141,13 @@
|
||||
"Click to add tags...": "Κάντε κλικ για να προσθέσετε ετικέτες...",
|
||||
"Client ID: %s": "Αναγνωριστικό προγράμματος-πελάτη: %s",
|
||||
"Close": "Κλείσιμο",
|
||||
"Close dropdown": "Κλείσιμο πτυσσόμενου μενού",
|
||||
"Close Window": "Κλείσιμο παραθύρου",
|
||||
"Code": "Κώδικας",
|
||||
"Code Block": "Μπλοκ Κώδικα",
|
||||
"Code View": "Προβολή κώδικα",
|
||||
"Collaborate on notebooks with others": "Συνεργασία σε σημειωματάρια με άλλους",
|
||||
"Collapse": "Collapse",
|
||||
"Coming alarms": "Προσεχείς ειδοποιήσεις",
|
||||
"Comma-separated list of paths to directories to load the certificates from, or path to individual cert files. For example: /my/cert_dir, /other/custom.pem. Note that if you make changes to the TLS settings, you must save your changes before clicking on \"Check synchronisation configuration\".": "Λίστα διαδρομών από φακέλους, διαχωρισμένων με κόμμα, για τη φόρτωση των πιστοποιητικών, ή διαδρομή των μεμονωμένων αρχείων πιστοποιητικών. Για παράδειγμα: /my/cert_dir, /other/custom.pem. Σημειώστε ότι αν κάνετε αλλαγές στις ρυθμίσεις TLS, πρέπει να αποθηκεύσετε τις αλλαγές σας πριν κάνετε κλικ στο \"Έλεγχος ρύθμισης παραμέτρων συγχρονισμού\".",
|
||||
"command": "εντολή",
|
||||
@@ -144,9 +165,12 @@
|
||||
"Conflicted: %d": "Με διένεξη: %d",
|
||||
"Conflicts": "Διενέξεις",
|
||||
"Conflicts (attachments)": "Διενέξεις (συνημμένα)",
|
||||
"Consolidated billing": "Ενοποιημένη χρέωση",
|
||||
"Content provided by %s": "Περιεχόμενο που παρέχεται από %s",
|
||||
"Continue": "Συνεχίστε",
|
||||
"Convert to note": "Μετατροπή σε σημείωση",
|
||||
"Convert to todo": "Μετατροπή σε to-do",
|
||||
"Converting speech to text...": "Μετατροπή της ομιλίας σε κείμενο...",
|
||||
"Copy": "Αντιγραφή",
|
||||
"Copy dev mode command to clipboard": "Αντιγραφή dev mode εντολής στο πρόχειρο",
|
||||
"Copy external link": "Αντιγραφή εξωτερικού συνδέσμου",
|
||||
@@ -162,9 +186,14 @@
|
||||
"Could not export notes: %s": "Δεν ήταν δυνατή η εξαγωγή σημειώσεων: %s",
|
||||
"Could not install plugin: %s": "Δεν ήταν δυνατή η εγκατάσταση του plugin: %s",
|
||||
"Could not respond to the invitation. Please try again, or check with the notebook owner if they are still sharing it.\n\nThe error was: \"%s\"": "Δεν μπόρεσε να ανταποκριθεί στην πρόσκληση. Προσπαθήστε ξανά ή επικοινωνήστε με τον ιδιοκτήτη του φορητού υπολογιστή, αν εξακολουθεί να το μοιράζεται.\n\nΤο σφάλμα ήταν: \"%s\"",
|
||||
"Could not switch profile: %s": "Δεν ήταν δυνατή η αλλαγή του plugin: %s",
|
||||
"Could not upgrade master key: %s": "Δεν ήταν δυνατή η αναβάθμιση του master κλειδιού: %s",
|
||||
"Could not verify the share status of this notebook - aborting. Please try again when you are connected to the internet.": "Δεν ήταν δυνατή η επαλήθευση της κατάστασης κοινής χρήσης αυτού του φορητού υπολογιστή - διακοπή. Προσπαθήστε ξανά όταν συνδεθείτε στο διαδίκτυο.",
|
||||
"Could not verify your identify: %s": "Δεν ήταν δυνατή η επαλήθευση της ταυτότητάς σας: %s",
|
||||
"Create": "Δημιουργία",
|
||||
"Create a new notebook under a parent notebook.": "Δημιουργήστε ένα νέο σημειωματάριο κάτω από ένα γονικό σημειωματάριο.",
|
||||
"Create a notebook": "Δημιουργία σημειωματάριου",
|
||||
"Create new profile...": "Δημιουργία νέου προφίλ...",
|
||||
"Create notebook": "Δημιουργία σημειωματαρίου",
|
||||
"Create user": "Δημιουργία χρήστη",
|
||||
"Created": "Δημιουργήθηκε",
|
||||
@@ -193,6 +222,7 @@
|
||||
"Date": "Ημερομηνία",
|
||||
"Date format": "Μορφή ημερομηνίας",
|
||||
"days": "ημέρες",
|
||||
"Decrease indent level": "Μείωση του επιπέδου εσοχής",
|
||||
"Decrypted items: %d": "Αποκρυπτογραφημένα στοιχεία: %d",
|
||||
"Decrypted items: %s / %s": "Αποκρυπτογραφημένα στοιχεία: %s / %s",
|
||||
"Decrypting items: %d/%d": "Αποκρυπτογράφηση αντικειμένων: %d/%d",
|
||||
@@ -209,8 +239,11 @@
|
||||
"Delete notebook \"%s\"?\n\nAll notes and sub-notebooks within this notebook will also be deleted.": "Διαγραφή σημειωματάριου \"%s\";\n\nΌλες οι σημειώσεις και τα υπο-σημειωματάρια που περιέχει θα διαγραφούν επίσης.",
|
||||
"Delete notebook? All notes and sub-notebooks within this notebook will also be deleted.": "Διαγραφή σημειωματάριου; Όλες οι σημειώσεις και τα υπο-σημειωματάρια θα διαγραφούν επίσης.",
|
||||
"Delete plugin \"%s\"?": "Διαγραφή plugin \"%s\";",
|
||||
"Delete profile \"%s\"": "Διαγραφή προφίλ \"%s\";",
|
||||
"Delete selected notes": "Διαγραφή επιλεγμένων σημειώσεων",
|
||||
"Delete these %d notes?": "Διαγραφή των σημειώσεων %d;",
|
||||
"Delete this invitation? The recipient will no longer have access to this shared notebook.": "Να διαγραφεί αυτή την πρόσκληση; Ο παραλήπτης δεν θα έχει πλέον πρόσβαση σε αυτό το κοινόχρηστο σημειωματάριο.",
|
||||
"Delete this profile?": "Να διαγραφεί αυτό το προφίλ;",
|
||||
"Deleted local items: %d.": "Διαγραμμένα τοπικά στοιχεία: %d.",
|
||||
"Deleted remote items: %d.": "Διαγραμμένα απομακρυσμένα στοιχεία: %d.",
|
||||
"Deletes the given notebook.": "Διαγράφει το καθορισμένο σημειωματάριο.",
|
||||
@@ -240,6 +273,7 @@
|
||||
"Do it now": "Κάνε το τώρα",
|
||||
"Do not ask for confirmation.": "Χωρίς να ζητείται επιβεβαίωση.",
|
||||
"Do not lose the password as, for security purposes, this will be the *only* way to decrypt the data! To enable encryption, please enter your password below.": "Μην χάσετε τον κωδικό πρόσβασης, καθώς, για λόγους ασφαλείας, αυτός θα είναι ο *μόνος* τρόπος αποκρυπτογράφησης των δεδομένων! Για να ενεργοποιήσετε την κρυπτογράφηση, εισαγάγετε τον κωδικό πρόσβασής σας παρακάτω.",
|
||||
"Done": "Ολοκληρώθηκε",
|
||||
"Download": "Λήψη",
|
||||
"Download and install the relevant extension for your browser:": "Κάντε λήψη και εγκατάσταση της αντίστοιχης επέκτασης για το πρόγραμμα περιήγησής σας:",
|
||||
"Downloaded": "Έχουν ληφθεί",
|
||||
@@ -253,17 +287,21 @@
|
||||
"Dropbox Login": "Σύνδεση Dropbox",
|
||||
"Duplicate": "Δημιουργία αντιγράφου",
|
||||
"Duplicate line": "Διπλασιασμός γραμμής",
|
||||
"Duplicate selected notes": "Διπλασιασμός επιλεγμένων γραμμών",
|
||||
"Duplicates the notes matching <note> to [notebook]. If no notebook is specified the note is duplicated in the current notebook.": "Αντιγράφει τις σημειώσεις που ταιριάζουν με τη <note> στο [σημειωματάριο]. Εάν δεν έχει οριστεί κανένα σημειωματάριο, η σημείωση αντιγράφεται στον τρέχον.",
|
||||
"Edit": "Επεξεργασία",
|
||||
"Edit in external editor": "Επεξεργασία σε εξωτερικό editor",
|
||||
"Edit link": "Επεξεργασία συνδέσμου",
|
||||
"Edit note.": "Eπεξεργασία σημείωσης.",
|
||||
"Edit notebook": "Επεξεργασία σημειωματάριου",
|
||||
"Edit profile": "Επεξεργασία προφίλ",
|
||||
"Editor": "Επεξεργασία",
|
||||
"Editor font": "Γραμματοσειρά editor",
|
||||
"Editor font family": "Οικογένεια γραμματοσειράς editor",
|
||||
"Editor font size": "Μέγεθος γραμματοσειράς editor",
|
||||
"Editor maximum width": "Μέγιστο πλάτος editor",
|
||||
"Editor monospace font family": "Οικογένεια μονοδιαστημικών γραμματοσειρών επεξεργαστή",
|
||||
"Editor: %s": "Συντάκτης: %s",
|
||||
"Either \"text\" or \"json\"": "Είτε \"text\" ή \"json\"",
|
||||
"Emacs": "Emacs",
|
||||
"Email": "Email",
|
||||
@@ -275,6 +313,7 @@
|
||||
"Enable ^sup^ syntax": "Ενεργοποίηση ^sup^ syntax",
|
||||
"Enable abbreviation syntax": "Ενεργοποίηση abbreviation syntax",
|
||||
"Enable audio player": "Ενεργοποίηση προγράμματος αναπαραγωγής ήχου",
|
||||
"Enable biometrics authentication?": "Ενεργοποίηση βιομετρικού ελέγχου ταυτότητας;",
|
||||
"Enable deflist syntax": "Ενεργοποίηση deflist syntax",
|
||||
"Enable encryption": "Ενεργοποίηση κρυπτογράφησης",
|
||||
"Enable footnotes": "Ενεργοποίηση footnotes",
|
||||
@@ -287,7 +326,9 @@
|
||||
"Enable note history": "Ενεργοποίηση ιστορικού σημειώσεων",
|
||||
"Enable PDF viewer": "Ενεργοποίηση προβολής PDF",
|
||||
"Enable soft breaks": "Ενεργοποίηση soft breaks",
|
||||
"Enable spellcheck in the text editor": "Ενεργοποίηση του ορθογραφικού ελέγχου στον επεξεργαστή κειμένου",
|
||||
"Enable table of contents extension": "Ενεργοποίηση επέκτασης table of contents",
|
||||
"Enable the Markdown toolbar": "Ενεργοποίηση της γραμμής εργαλείων Markdown",
|
||||
"Enable typographer support": "Ενεργοποίηση υποστήριξης typographer",
|
||||
"Enable video player": "Ενεργοποίηση προγράμματος αναπαραγωγής βίντεο",
|
||||
"Enable Web Clipper Service": "Ενεργοποίηση υπηρεσίας Web Clipper",
|
||||
@@ -314,6 +355,7 @@
|
||||
"Evernote Export File (as HTML)": "Αρχείο εξαγωγής Evernote (σαν HTML)",
|
||||
"Evernote Export File (as Markdown)": "Αρχείο εξαγωγής Evernote (σαν Markdown)",
|
||||
"Exits the application.": "Βγαίνει από την εφαρμογή.",
|
||||
"Expand": "Επέκταση",
|
||||
"Export": "Εξαγωγή",
|
||||
"Export all": "Εξαγωγή όλων",
|
||||
"Export debug report": "Εξαγωγή Debug report",
|
||||
@@ -332,6 +374,9 @@
|
||||
"Fetching resources: %d/%d": "Λήψη πόρων: %d/%d",
|
||||
"File": "Αρχείο",
|
||||
"File system": "Σύστημα Αρχείων",
|
||||
"Filter tags": "Φίλτρο ετικετών",
|
||||
"Find and replace": "Εύρεση και αντικατάσταση",
|
||||
"Find: ": "Found: %d.",
|
||||
"Firefox Extension": "Επέκταση Firefox",
|
||||
"Fix search index": "Διόρθωση ευρετηρίων αναζήτησης",
|
||||
"Fixing search index...": "Διόρθωση ευρετηρίων αναζήτησης...",
|
||||
@@ -340,14 +385,17 @@
|
||||
"Focus title": "Eστίαση στον τίτλο",
|
||||
"Folders": "Φάκελοι",
|
||||
"For debugging purpose only: export your profile to an external SD card.": "Για τον εντοπισμό σφαλμάτων και μόνο: εξαγάγετε το προφίλ σας σε μια εξωτερική κάρτα SD.",
|
||||
"For example \"%s\"": "Για παράδειγμα \"%s\"",
|
||||
"For information on how to customise the shortcuts please visit %s": "Για πληροφορίες σχετικά με τον τρόπο προσαρμογής των συντομεύσεων, επισκεφτείτε το %s",
|
||||
"For more information about End-To-End Encryption (E2EE) and advice on how to enable it please check the documentation:": "Για περισσότερες πληροφορίες σχετικά με την κρυπτογράφηση End-To-End (E2EE) και συμβουλές σχετικά με τον τρόπο ενεργοποίησής της, ελέγξτε το εγχειρίδιο:",
|
||||
"For the list of keyboard shortcuts and config options, type `help keymap`": "Για τη λίστα των συντομεύσεων πληκτρολογίου και των ρυθμίσεων, πληκτρολογήστε `help keymap`",
|
||||
"Force path style": "Επιβολή path style",
|
||||
"Formatting": "Μορφοποίηση",
|
||||
"Forward": "Μπροστά",
|
||||
"Found: %d.": "Βρέθηκε: %d.",
|
||||
"FTS enabled: %d": "FTS ενεργοποιημένο: %d",
|
||||
"Full changelog": "Πλήρες αρχείο αλλαγών",
|
||||
"Full name": "Ονοματεπώνυμο",
|
||||
"General": "Γενικά",
|
||||
"Generated": "Δημιουργήθηκε",
|
||||
"Generating link...": "Δημιουργία συνδέσμου...",
|
||||
@@ -357,11 +405,18 @@
|
||||
"Go to source URL": "Μεταβείτε στη διεύθυνση URL προέλευσης",
|
||||
"Goto Anything...": "Γρήγορη Μετακίνηση...",
|
||||
"Grant authorisation": "Έγκριση εξουσιοδότησης",
|
||||
"Header %d": "Επικεφαλίδα %d",
|
||||
"Headers": "Κεφαλίδες",
|
||||
"Heading": "Επικεφαλίδα",
|
||||
"Help": "Βοήθεια",
|
||||
"Hermes enabled: %d": "Hermes ενεργοποιημένο: %d",
|
||||
"Hide %s": "Απόκρυψη %s",
|
||||
"Hide advanced": "Απόκρυψη προηγμένων",
|
||||
"Hide disabled": "Απόκρυψη απενεργοποιημένων",
|
||||
"Hide disabled keys": "Απόκρυψη απενεργοποιημένων κλειδιών",
|
||||
"Hide Joplin": "Κρύψε το Joplin",
|
||||
"Hide keyboard": "Απόκρυψη πληκτρολογίου",
|
||||
"Hide more actions": "Απόκρυψη περισσότερων ενεργειών",
|
||||
"Highlight": "Επισήμανση",
|
||||
"Home": "Home",
|
||||
"Horizontal Rule": "Οριζόντια Διαγράμμιση",
|
||||
@@ -386,12 +441,14 @@
|
||||
"In order to use the web clipper, you need to do the following:": "Για να χρησιμοποιήσετε το web clipper, πρέπει να κάνετε τα εξής:",
|
||||
"In progress": "Σε εξέλιξη",
|
||||
"In: %s": "Στο: %s",
|
||||
"Increase indent level": "Αύξηση του επιπέδου εσοχής",
|
||||
"Indent less": "Μείωση εσοχής",
|
||||
"Indent more": "Αύξηση εσοχής",
|
||||
"Information": "Πληροφορίες",
|
||||
"Inline Code": "Ενσωματωμένος κώδικας",
|
||||
"Insert": "Εισαγωγή",
|
||||
"Insert Hyperlink": "Εισαγωγή υπερσύνδεσης",
|
||||
"Insert time": "Εισαγωγή ώρας",
|
||||
"Install": "Εγκατάσταση",
|
||||
"Install from file": "Εγκατάσταση από αρχείο",
|
||||
"Installed": "Εγκαταστάθηκε",
|
||||
@@ -407,6 +464,7 @@
|
||||
"Items": "Στοιχεία",
|
||||
"Items that cannot be decrypted": "Στοιχεία που δεν μπορούν αποκρυπτογραφηθούν",
|
||||
"Items that cannot be synchronised": "Στοιχεία που δεν μπορούν να συγχρονιστούν",
|
||||
"Join us on Twitter": "Ακολουθήστε μας στο Twitter",
|
||||
"Joplin can synchronise your notes using various providers. Select one from the list below.": "Το Joplin μπορεί να συγχρονίσει τις σημειώσεις σας χρησιμοποιώντας διάφορους παρόχους. Επιλέξτε έναν από τον παρακάτω κατάλογο.",
|
||||
"Joplin Cloud": "Joplin Cloud",
|
||||
"Joplin Cloud email": "Joplin Cloud email",
|
||||
@@ -422,6 +480,7 @@
|
||||
"Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.": "Το Joplin Web Clipper επιτρέπει την αποθήκευση ιστοσελίδων και screenshots από το πρόγραμμα περιήγησης στο Joplin.",
|
||||
"Joplin website": "Joplin website",
|
||||
"Joplin's own sync service. Also gives access to Joplin-specific features such as publishing notes or collaborating on notebooks with others.": "Η υπηρεσία συγχρονισμού του Joplin. Παρέχει επίσης πρόσβαση σε ειδικές λειτουργίες του Joplin, όπως η δημοσίευση σημειώσεων ή η συνεργασία σε σημειωματάρια με άλλους.",
|
||||
"KaTeX": "KaTeX",
|
||||
"Keep note history for": "Διατήρηση ιστορικού σημειώσεων για",
|
||||
"Keyboard Mode": "Λειτουργία πληκτρολογίου",
|
||||
"Keyboard Shortcut": "Συντόμευση πληκτρολογίου",
|
||||
@@ -439,10 +498,15 @@
|
||||
"Letter": "Letter",
|
||||
"Light": "Light",
|
||||
"Lines": "Γραμμές",
|
||||
"Link": "Σύνδεσμος",
|
||||
"Link description": "Περιγραφή συνδέσμου",
|
||||
"Link has been copied to clipboard!": "Ο σύνδεσμος έχει αντιγραφεί στο πρόχειρο!",
|
||||
"Link text": "Κείμενο συνδέσμου",
|
||||
"Links with protocol \"%s\" are not supported": "Σύνδεσμοι με πρωτόκολλο \"%s\" δεν υποστηρίζονται",
|
||||
"List item": "Στοιχείο λίστας",
|
||||
"Lists": "Λίστες",
|
||||
"Loaded": "Φορτωμένα",
|
||||
"Loading...": "Φόρτωση...",
|
||||
"Location": "Τοποθεσία",
|
||||
"Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at \"%s\" and resume the operation.": "Το αρχείο κλειδώματος έχει ήδη δημιουργηθεί. Αν γνωρίζετε ότι δεν πραγματοποιείται συγχρονισμός, μπορείτε να διαγράψετε το αρχείο κλειδώματος στο \"%s\" και να συνεχίσετε τη λειτουργία.",
|
||||
"Log": "Log",
|
||||
@@ -455,6 +519,8 @@
|
||||
"Make a donation": "Κάντε μια δωρεά",
|
||||
"Manage master password": "Διαχείριση κύριου κωδικού πρόσβασης",
|
||||
"Manage master password...": "Διαχείριση κύριου κωδικού πρόσβασης...",
|
||||
"Manage multiple users": "Διαχείριση πολλαπλών χρηστών",
|
||||
"Manage profiles": "Διαχείριση προφίλ",
|
||||
"Manage your plugins": "Διαχείριση των επεκτάσεων",
|
||||
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, `status`, `decrypt-file`, and `target-status`.": "Διαχειρίζεται τη διαμόρφωση E2EE. Οι εντολές είναι `enable`, `disable`, `decrypt`, `status`, `decrypt-file`, και `target-status`.",
|
||||
"Manual": "Χειροκίνητα",
|
||||
@@ -467,9 +533,13 @@
|
||||
"Master password": "Κύριος κωδικός πρόσβασης",
|
||||
"Master password:": "Κύριος κωδικός πρόσβασης:",
|
||||
"Max concurrent connections": "Μέγιστος αριθμός ταυτόχρονων συνδέσεων",
|
||||
"Max Item Size": "Μέγιστο μέγεθος αντικειμένου",
|
||||
"Max note or attachment size": "Μέγιστο μέγεθος σημείωσης ή συνημμένου",
|
||||
"Max Total Size": "Μέγιστο συνολικό μέγεθος",
|
||||
"Missing keys": "Απουσία κλειδιών",
|
||||
"Missing Master Keys": "Απουσία κυρίως κλειδιών",
|
||||
"Missing required argument: %s": "Λείπει το απαιτούμενο όρισμα: %s",
|
||||
"Missing required flag value: %s": "Λείπει το απαιτούμενο flag: %s",
|
||||
"Mobile data - auto-sync disabled": "Δεδομένα κινητής τηλεφωνίας - ο αυτόματος συγχρονισμός απενεργοποιήθηκε",
|
||||
"More info": "Περισσότερες πληροφορίες",
|
||||
"More information": "Περισσότερες πληροφορίες",
|
||||
@@ -478,6 +548,7 @@
|
||||
"Move to notebook": "Μετακίνηση στο σημειωματάριο",
|
||||
"Move to notebook...": "Μετακίνηση στο σημειωματάριο...",
|
||||
"Move to notebook:": "Μετακίνηση στο σημειωματάριο:",
|
||||
"Moves the given <item> to [notebook]": "Μετακινεί το συγκεκριμένο <item> στο [notebook]",
|
||||
"n": "ο",
|
||||
"N": "Ο",
|
||||
"New note": "Νέα σημείωση",
|
||||
@@ -488,6 +559,7 @@
|
||||
"New tags:": "Νέες ετικέτες:",
|
||||
"New to-do": "Νέο to-do",
|
||||
"New version: %s": "Νέα έκδοση: %s",
|
||||
"Next match": "Επόμενη αντιστοίχιση",
|
||||
"Nextcloud": "Nextcloud",
|
||||
"Nextcloud password": "Nextcloud password",
|
||||
"Nextcloud username": "Nextcloud username",
|
||||
@@ -508,6 +580,7 @@
|
||||
"Not authentified with %s. Please provide any missing credentials.": "Δεν έγινε επαλήθευση με το %s. Παρακαλώ καταχωρίστε τα διαπιστευτήρια που λείπουν.",
|
||||
"Not downloaded": "Δεν έγινε λήψη",
|
||||
"Not generated": "Δεν δημιουργήθηκαν",
|
||||
"Not now": "Αργότερα",
|
||||
"note": "σημείωση",
|
||||
"Note": "Σημείωση",
|
||||
"Note area growth factor": "Συντελεστής ανάπτυξης περιοχής σημειώσεων",
|
||||
@@ -515,6 +588,7 @@
|
||||
"Note attachments...": "Επισυναπτόμενα...",
|
||||
"Note body": "Σώμα σημειώσεων",
|
||||
"Note does not exist: \"%s\". Create it?": "Δεν υπάρχει η σημείωση : \"%s\". Να δημιουργηθεί;",
|
||||
"Note editor": "Συντάκτης σημείωσης",
|
||||
"Note has been saved.": "Η σημείωση έχει αποθηκευτεί.",
|
||||
"Note History": "Ιστορικό Σημειώσεων",
|
||||
"Note is not a to-do: \"%s\"": "Η σημείωση δεν είναι to-do: \"%s\"",
|
||||
@@ -545,12 +619,14 @@
|
||||
"Only one note can be printed at a time.": "Μόνο μία σημείωση τη φορά μπορεί να εκτυπωθεί.",
|
||||
"Open": "Άνοιγμα",
|
||||
"Open %s": "Άνοιγμα %s",
|
||||
"Open PDF viewer": "Άνοιγμα προγράμματος προβολής PDF",
|
||||
"Open profile directory": "Άνοιγμα φακέλου προφίλ",
|
||||
"Open Sync Wizard...": "Άνοιγμα Οδηγού συγχρονισμού...",
|
||||
"Open...": "Άνοιγμα...",
|
||||
"Operation cancelled": "Η λειτουργία ακυρώθηκε",
|
||||
"Options": "Επιλογές",
|
||||
"Or create an account.": "Ή δημιουργείστε ένα λογαριασμό.",
|
||||
"Ordered list": "Ταξινομημένη λίστα",
|
||||
"Other applications...": "Άλλες εφαρμογές...",
|
||||
"Output format: %s": "Μορφή εξόδου: %s",
|
||||
"Page orientation for PDF export": "Προσανατολισμός σελίδας για εξαγωγή PDF",
|
||||
@@ -560,14 +636,18 @@
|
||||
"Password:": "Κωδικός:",
|
||||
"Passwords do not match!": "Ο κωδικός πρόσβασης δεν μπορεί να είναι κενός!",
|
||||
"Paste": "Επικόλληση",
|
||||
"Paste as text": "Επικόλληση ως κείμενο",
|
||||
"Path:": "Διαδρομή:",
|
||||
"PDF File": "Αρχείο PDF",
|
||||
"Per user. Minimum of %d users.": "Ανά χρήστη. Τουλάχιστον %d χρήστες.",
|
||||
"Permission needed": "Απαιτείται άδεια",
|
||||
"Permission to use camera": "Άδεια χρήσης κάμερας",
|
||||
"Please click on \"%s\" to proceed, or set the passwords in the \"%s\" list below.": "Κάντε κλικ στο \"%s\" για να συνεχίσετε ή ορίστε τους κωδικούς πρόσβασης στην παρακάτω λίστα \"%s\".",
|
||||
"Please confirm that you would like to re-encrypt your complete database.": "Επιβεβαιώστε ότι θέλετε να ξανακρυπτογραφήσετε την πλήρη βάση δεδομένων σας.",
|
||||
"Please enter your password in the master key list below before upgrading the key.": "Εισαγάγετε τον κωδικό πρόσβασής σας στη λίστα του master κλειδιού πριν αναβαθμίσετε το κλειδί.",
|
||||
"Please note that if it is a large notebook, it may take a few minutes for all the notes to show up on the recipient's device.": "Λάβετε υπόψη ότι αν πρόκειται για ένα μεγάλο σημειωματάριο, μπορεί να χρειαστούν μερικά λεπτά για να εμφανιστούν όλες οι σημειώσεις στη συσκευή του παραλήπτη.",
|
||||
"Please open the following URL in your browser to authenticate the application. The application will create a directory in \"Apps/Joplin\" and will only read and write files in this directory. It will have no access to any files outside this directory nor to any other personal data. No data will be shared with any third party.": "Παρακαλώ ανοίξτε την ακόλουθη διεύθυνση URL στο πρόγραμμα περιήγησής σας για να πιστοποιήσετε την εφαρμογή. Η εφαρμογή θα δημιουργήσει έναν φάκελο στο \"Apps / Joplin\" και θα διαβάζει και θα γράφει μόνο αρχεία σε αυτόν. Δεν θα έχει πρόσβαση σε αρχεία εκτός αυτού του φακέλου ούτε σε άλλα προσωπικά δεδομένα. Δεν πρόκειται να κοινοποιηθούν δεδομένα σε τρίτους.",
|
||||
"Please record your voice...": "Παρακαλώ καταγράψτε τη φωνή σας...",
|
||||
"Please select a notebook first.": "Παρακαλώ επιλέξτε πρώτα σημειωματάριο.",
|
||||
"Please select the note or notebook to be deleted first.": "Παρακαλώ πρώτα επιλέξτε τη σημείωση ή το σημειωματάριο που θέλετε να διαγραφτεί.",
|
||||
"Please select where the sync status should be exported to": "Επιλέξτε την τοποθεσία στην οποία θα εξαχθεί η κατάσταση του συγχρονισμού",
|
||||
@@ -589,15 +669,24 @@
|
||||
"Press the shortcut": "Πατήστε τη συντόμευση",
|
||||
"Press the shortcut and then press ENTER. Or, press BACKSPACE to clear the shortcut.": "Πατήστε τη συντόμευση και, στη συνέχεια, πατήστε το πλήκτρο ENTER. Εναλλακτικά, πατήστε το πλήκτρο BACKSPACE για να καταργήσετε τη συντόμευση.",
|
||||
"Press to set the decryption password.": "Πατήστε για να ορίσετε τον κωδικό αποκρυπτογράφησης.",
|
||||
"Previous match": "Προηγούμενη αντιστοίχιση",
|
||||
"Previous versions of this note": "Προηγούμενες εκδόσεις αυτής της σημείωσης",
|
||||
"Print": "Εκτύπωση",
|
||||
"Priority support": "Υποστήριξη προτεραιότητας",
|
||||
"Privacy Policy": "Πολιτική Προστασίας Προσωπικών Δεδομένων",
|
||||
"Pro": "Pro",
|
||||
"Process failed payment subscriptions": "Επεξεργασία αποτυχημένων συνδρομών πληρωμής",
|
||||
"Process oversized accounts": "Επεξεργασία υπερμεγεθών λογαριασμών",
|
||||
"Process user deletions": "Επεξεργασία διαγραφών χρηστών",
|
||||
"Profile": "Προφιλ",
|
||||
"Profile name": "Όνομα προφίλ",
|
||||
"Profile name:": "Όνομα προφιλ:",
|
||||
"Profile Version: %s": "Έκδοση προφίλ: %s",
|
||||
"Profiles": "Προφιλ",
|
||||
"Properties": "Ιδιότητες",
|
||||
"Proxy enabled": "Ενεργοποίηση διακομιστή μεσολάβησης",
|
||||
"Proxy timeout (seconds)": "Χρονικό όριο μεσολάβησης (δευτερόλεπτα)",
|
||||
"Proxy URL": "URL διακομιστή μεσολάβησης",
|
||||
"Public-private key pair:": "Ζεύγος δημόσιου-ιδιωτικού κλειδιού:",
|
||||
"Publish note...": "Δημοσίευση σημείωσης...",
|
||||
"Publish Notes": "Δημοσίευση σημειώσεων",
|
||||
@@ -614,6 +703,7 @@
|
||||
"Recipients:": "Αποδέκτες:",
|
||||
"Redo": "Επανάληψη",
|
||||
"Refresh": "Ανανέωση",
|
||||
"Regular expression": "Regular expression",
|
||||
"Reject": "Απόρριψη",
|
||||
"Remove": "Κατάργηση",
|
||||
"Remove tag \"%s\" from all notes?": "Κατάργηση της ετικέτας \"%s\" από όλες τις σημειώσεις;",
|
||||
@@ -623,6 +713,11 @@
|
||||
"Rename tag:": "Μετονομασία ετικέτας:",
|
||||
"Renames the given <item> (note or notebook) to <name>.": "Μετονομάζει το καθορισμένο <item> (σημείωση ή σημειωματάριο) στο <name>.",
|
||||
"Renew token": "Ανανέωση token",
|
||||
"Replace": "Αντικατάσταση",
|
||||
"Replace all": "Αντικατάσταση όλων",
|
||||
"Replace with...": "Αντικατάσταση με...",
|
||||
"Replace: ": "Αντικατάσταση: ",
|
||||
"Reset application layout": "Αλλαγή διάταξης εφαρμογής",
|
||||
"Reset master password": "Επαναφορά κύριου κωδικού πρόσβασης",
|
||||
"Resources: %d.": "Πόροι: %d.",
|
||||
"Restart and upgrade": "Επανεκκίνηση και αναβάθμιση",
|
||||
@@ -645,11 +740,13 @@
|
||||
"Safe mode is currently active. Note rendering and all plugins are temporarily disabled.": "Η ασφαλής λειτουργία είναι ενεργή αυτήν τη στιγμή. Σημειώστε ότι η απόδοση και όλα τα πρόσθετα απενεργοποιούνται προσωρινά.",
|
||||
"Save": "Αποθήκευση",
|
||||
"Save alarm": "Αποθήκευση ειδοποίησης",
|
||||
"Save as %s": "Αποθήκευση ως %s",
|
||||
"Save as...": "Αποθήκευση ως...",
|
||||
"Save changes": "Αποθήκευση αλλαγών",
|
||||
"Save geo-location with notes": "Αποθήκευση της γεωγραφικής τοποθεσίας μαζί με της σημειώσεις",
|
||||
"Search": "Εύρεση",
|
||||
"Search for plugins...": "Αναζήτηση για plugins...",
|
||||
"Search for...": "Αναζήτηση για...",
|
||||
"Search in all the notes": "Αναζήτηση σε όλες τις σημειώσεις",
|
||||
"Search in current note": "Αναζήτηση στην τρέχουσα σημείωση",
|
||||
"Search...": "Αναζήτηση...",
|
||||
@@ -660,6 +757,7 @@
|
||||
"Select all": "Επιλογή όλων",
|
||||
"Select emoji...": "Επιλογή emoji...",
|
||||
"Select file...": "Επιλογή φακέλου...",
|
||||
"Select parent notebook": "Επιλέξτε γονικό σημειωματάριο",
|
||||
"Server is already running on port %d": "Ο διακομιστής εκτελείται ήδη στη θύρα %d",
|
||||
"Server is not running.": "Ο διακομιστής δεν εκτελείται.",
|
||||
"Server is running on port %d": "Ο διακομιστής εκτελείται στη θύρα %d",
|
||||
@@ -669,17 +767,23 @@
|
||||
"Set the password": "Ορισμός κωδικού πρόσβασης",
|
||||
"Sets the property <name> of the given <note> to the given [value]. Possible properties are:\n\n%s": "Ορίζει την ιδιότητα <name> του καθορισμένου <note> στην καθορισμένη [τιμή]. Πιθανές ιδιότητες είναι:\n\n%s",
|
||||
"Share": "Κοινοποίηση",
|
||||
"Share and collaborate on a notebook": "Μοιραστείτε και συνεργαστείτε σε ένα σημειωματάριο",
|
||||
"Share Notebook": "Κοινοποίηση Σημειωματάριου",
|
||||
"Share notebook...": "Κοινοποίηση σημειωματάριου...",
|
||||
"Sharing access control": "Έλεγχος πρόσβασης κοινής χρήσης",
|
||||
"Sharing notebook...": "Κοινοποίηση σημειωματάριου...",
|
||||
"Shortcuts are not available in CLI mode.": "Οι συντομεύσεις δεν είναι διαθέσιμες στη λειτουργία CLI.",
|
||||
"Show advanced": "Εμφάνιση επιλογών για προχωρημένους",
|
||||
"Show Advanced Settings": "Εμφάνιση επιλογών για προχωρημένους",
|
||||
"Show all": "Εμφάνιση όλων",
|
||||
"Show completed to-dos": "Εμφάνιση ολοκληρωμένων to-dos",
|
||||
"Show disabled": "Εμφάνιση απενεργοποιημένων",
|
||||
"Show disabled keys": "Εμφάνιση απενεργοποιημένων κλειδιών",
|
||||
"Show more actions": "Εμφάνιση περισσότερων ενεργειών",
|
||||
"Show note counts": "Εμφάνιση πλήθους σημειώσεων",
|
||||
"Show sort order buttons": "Εμφάνιση κουμπιών σειράς ταξινόμησης",
|
||||
"Show tray icon": "Εμφάνιση εικονιδίου στη γραμμή εργασιών",
|
||||
"Show/hide the sidebar": "Εμφάνιση/απόκρυψη της πλευρικής μπάρας",
|
||||
"Sidebar": "Πλευρική μπάρα",
|
||||
"Size": "Μέγεθος",
|
||||
"Skip this version": "Παραλείψτε αυτή την έκδοση",
|
||||
@@ -715,6 +819,7 @@
|
||||
"Step 2: Install the extension": "Βήμα 2: Εγκαταστήστε την επέκταση",
|
||||
"Stop": "Σταμάτημα",
|
||||
"Stop external editing": "Διακοπή εξωτερικής επεξεργασίας",
|
||||
"Storage space": "Χώρος αποθήκευσης",
|
||||
"Strikethrough": "Διακριτή διαγραφή",
|
||||
"strong text": "έντονη γραφή",
|
||||
"Submit": "Yποβολή",
|
||||
@@ -724,9 +829,12 @@
|
||||
"Swap line down": "Αλλαγή γραμμής με την κάτω",
|
||||
"Swap line up": "Αλλαγή γραμμής με την πανω",
|
||||
"Switch between note and to-do type": "Εναλλαγή μεταξύ σημείωσης και to-do",
|
||||
"Switch profile": "Αλλαγή προφίλ",
|
||||
"Switch to note type": "Αλλαγή σε σημείωση",
|
||||
"Switch to profile %d": "Αλλαγή στο προφίλ %d",
|
||||
"Switch to to-do type": "Αλλαγή σε to-do",
|
||||
"Switches to [notebook] - all further operations will happen within this notebook.": "Αλλάζει σε [σημειωματάριο] - όλες οι περαιτέρω λειτουργίες θα πραγματοποιηθούν μέσα σε αυτό το σημειωματάριο.",
|
||||
"Sync as many devices as you want": "Συγχρονίστε όσες συσκευές επιθυμείτε",
|
||||
"Sync Status": "Κατάσταση Συγχρονισμού",
|
||||
"Sync status (synced items / total items)": "Κατάσταση συγχρονισμού (συγχρονισμένα στοιχεία / σύνολο αρχείων)",
|
||||
"Sync target must be upgraded! Run `%s` to proceed.": "Ο προορισμός συγχρονισμού πρέπει να αναβαθμιστεί! Εκτελέστε το `%s` για να συνεχίσετε.",
|
||||
@@ -746,13 +854,18 @@
|
||||
"Synchronising...": "Συγχρονισμός...",
|
||||
"Synchronizing...": "Συγχρονισμός...",
|
||||
"Tabloid": "Tabloid",
|
||||
"tag1, tag2, ...": "tag1, tag2, ...",
|
||||
"Tagged: %d.": "Με ετικέτα: %d.",
|
||||
"Tags": "Ετικέτες",
|
||||
"Take photo": "Βγάλτε μια φωτογραφία",
|
||||
"Task list": "Λίστα εργασιών",
|
||||
"Tasks": "Εργασίες",
|
||||
"Teams": "Ομάδες",
|
||||
"Text editor command": "Εντολή \"Επεξεργαστή κειμένου\"",
|
||||
"Thank you! Your Joplin Cloud account is now setup and ready to use.": "Ευχαριστώ! Ο λογαριασμός σας στο Joplin Cloud είναι τώρα ρυθμισμένος και έτοιμος για χρήση.",
|
||||
"The active profile cannot be deleted. Switch to a different profile and try again.": "Το ενεργό προφίλ δεν μπορεί να διαγραφεί. Μεταβείτε σε ένα άλλο προφίλ και δοκιμάστε ξανά.",
|
||||
"The app is now going to close. Please relaunch it to complete the process.": "Η εφαρμογή θα κλείσει τώρα. Παρακαλώ ανοίξτε την ξανά για να ολοκληρώσετε τη διαδικασία.",
|
||||
"The application did not close properly. Would you like to start in safe mode?": "Η εφαρμογή δεν έκλεισε σωστά. Θα θέλατε να ξεκινήσετε σε ασφαλή λειτουργία;",
|
||||
"The application has been authorised - you may now close this browser tab.": "Η εφαρμογή έχει εξουσιοδοτηθεί - μπορείτε τώρα να κλείσετε αυτήν την καρτέλα του προγράμματος περιήγησης.",
|
||||
"The application has been authorised!": "Η εφαρμογή έχει εγκριθεί!",
|
||||
"The application has been successfully authorised.": "Η εφαρμογή έχει εξουσιοδοτηθεί με επιτυχία.",
|
||||
@@ -762,6 +875,7 @@
|
||||
"The default admin password is insecure and has not been changed! [Change it now](%s)": "Ο προεπιλεγμένος κωδικός πρόσβασης διαχειριστή δεν είναι ασφαλής και δεν έχει αλλάξει! [Αλλάξτε τον τώρα] (%s)",
|
||||
"The default encryption method has been changed to a more secure one and it is recommended that you apply it to your data.": "Η προεπιλεγμένη μέθοδος κρυπτογράφησης έχει αλλάξει μία σε πιο ασφαλή και συνιστάται να την εφαρμόσετε στα δεδομένα σας.",
|
||||
"The default encryption method has been changed, you should re-encrypt your data.": "Η προεπιλεγμένη μέθοδος κρυπτογράφησης έχει αλλάξει, θα πρέπει να κρυπτογραφήσετε εκ νέου τα δεδομένα σας.",
|
||||
"The default profile cannot be deleted": "Το προεπιλεγμένο προφίλ δεν μπορεί να διαγραφεί",
|
||||
"The editor command (may include arguments) that will be used to open a note. If none is provided it will try to auto-detect the default editor.": "Η εντολή του editor (που μπορεί να περιλαμβάνει ορίσματα) θα χρησιμοποιηθεί για το άνοιγμα μιας σημείωσης. Εάν δεν δωθεί καμία, θα προσπαθήσει να ανιχνεύσει αυτόματα το προεπιλεγμένο πρόγραμμα επεξεργασίας.",
|
||||
"The factor property sets how the item will grow or shrink to fit the available space in its container with respect to the other items. Thus an item with a factor of 2 will take twice as much space as an item with a factor of 1.Restart app to see changes.": "Ο συντελεστής ανάπτυξης καθορίζει το πόσο θα αναπτυχθεί ή θα συρρίκνωθεί το αντικειμένο ώστε να χωρά στον διαθέσιμο χώρο σε σχέση με τα άλλα αντικείμενα. Έτσι, ένα στοιχείο με συντελεστή 2 θα πάρει διπλάσιο χώρο από ένα στοιχείο με συντελεστή 1. Επανεκκινήστε την εφαρμογή για να δείτε αλλαγές.",
|
||||
"The following attachments are being watched for changes:": "Τα ακόλουθα συνημμένα παρακολουθούνται για αλλαγές:",
|
||||
@@ -783,8 +897,10 @@
|
||||
"The Web Clipper needs your authorisation to access your data.": "Το Web Clipper χρειάζεται την άδειά σας για να αποκτήσει πρόσβαση στα δεδομένα σας.",
|
||||
"The web clipper service is enabled and set to auto-start.": "Η υπηρεσία web clipper είναι ενεργοποιημένη και έχει ρυθμιστεί για αυτόματη εκκίνηση.",
|
||||
"The web clipper service is not enabled.": "Η υπηρεσία Web Clipper δεν είναι ενεργοποιημένη.",
|
||||
"The WebDAV implementation of %s is incompatible with Joplin, and as such is no longer supported. Please use a different sync method.": "Η υλοποίηση WebDAV του %s δεν είναι συμβατή με το Joplin και ως εκ τούτου δεν υποστηρίζεται πλέον. Παρακαλούμε χρησιμοποιήστε μια διαφορετική μέθοδο συγχρονισμού.",
|
||||
"Theme": "Θέμα",
|
||||
"There are currently no notes. Create one by clicking on the (+) button.": "Δεν υπάρχουν προς το παρόν σημειώσεις. Δημιουργήστε μία κάνοντας κλικ στο κουμπί (+).",
|
||||
"There are unsaved changes.": "Υπάρχουν μη αποθηκευμένες αλλαγές.",
|
||||
"There is currently no notebook. Create one by clicking on \"New notebook\".": "Δεν υπάρχει κανένα σημειωματάριο. Δημιουργήστε ένα πατώντας στο \"Νέο σημειωματάριο\".",
|
||||
"There is no data to export.": "Δεν υπάρχουν δεδομένα για εξαγωγή.",
|
||||
"There was a [conflict](%s) on the attachment below.\n\n%s": "Υπήρξε μια [διένεξη](%s) στο παρακάτω συνημμένο.\n\n%s",
|
||||
@@ -818,8 +934,10 @@
|
||||
"To maximise/minimise the console, press \"tc\".": "Για μεγιστοποιήση/ελαχιστοποιήση της κονσόλας, πατήστε \"tc\".",
|
||||
"To move from one pane to another, press Tab or Shift+Tab.": "Για να μετακινηθείτε από ένα παράθυρο σε άλλο, πατήστε Tab ή Shift + Tab.",
|
||||
"To retry decryption of these items. Run `e2ee decrypt --retry-failed-items`": "Για να επαναλάβετε την αποκρυπτογράφηση αυτών των στοιχείων. Τρέξτε `e2ee decrypt --retry-failed-items`",
|
||||
"To switch the profile, the app is going to close and you will need to restart it.": "Για να αλλάξετε το προφίλ, η εφαρμογή θα κλείσει και θα πρέπει να την επανεκκινήσετε.",
|
||||
"To work correctly, the app needs the following permissions. Please enable them in your phone settings, in Apps > Joplin > Permissions": "Για να λειτουργήσει σωστά, η εφαρμογή χρειάζεται τα ακόλουθα δικαιώματα. Ενεργοποιήστε τα στις ρυθμίσεις του τηλεφώνου σας, στο Apps> Joplin> Permissions",
|
||||
"to-do": "to-do",
|
||||
"to-do: %s": "to-do: %s",
|
||||
"Toggle comment": "Εναλλαγή σχολίου",
|
||||
"Toggle development tools": "Εναλλαγή εργαλείων προγραμματισμού",
|
||||
"Toggle editor layout": "Εναλλαγή διάταξης editor",
|
||||
@@ -832,8 +950,10 @@
|
||||
"Toggle sort order field": "Εναλλαγή του πεδίου ταξινόμησης",
|
||||
"Token has been copied to the clipboard!": "Το Token έχει αντιγραφεί στο πρόχειρο!",
|
||||
"Tools": "Εργαλεία",
|
||||
"Total Size": "Συνολικό μέγεθος",
|
||||
"Total: %d/%d": "Σύνολο: %d/%d",
|
||||
"Try again": "Δοκιμάστε ξανά",
|
||||
"Try it now": "Δοκιμάστε το τώρα",
|
||||
"Type `help [command]` for more information about a command; or type `help all` for the complete usage information.": "Πληκτρολογήστε `help [command]` για περισσότερες πληροφορίες σχετικά με μια εντολή, ή πληκτρολογήστε `help all` για όλες τις πληροφορίες χρήσης.",
|
||||
"Type `joplin help` for usage information.": "Πληκτρολογήστε `joplin help` για πληροφορίες χρήσης.",
|
||||
"Type a note title or part of its content to jump to it. Or type # followed by a tag name, or @ followed by a notebook name. Or type : to search for commands.": "Πληκτρολογήστε έναν τίτλο σημείωσης ή μέρος του περιεχομένου του για να μεταβείτε σε αυτόν. Ή πληκτρολογήστε # ακολουθούμενο από ένα όνομα ετικέτας ή @ ακολουθούμενο από ένα σημειωματάριο. Ή πληκτρολογίστε : για να ψάξετε για εντολές.",
|
||||
@@ -843,6 +963,7 @@
|
||||
"Undo": "Αναίρεση",
|
||||
"Unknown flag: %s": "Άγνωστο flag: %s",
|
||||
"Unknown item type downloaded - please upgrade Joplin to the latest version": "Λήψη άγνωστου τύπου στοιχείου - αναβαθμίστε το Joplin στην πιο πρόσφατη έκδοση",
|
||||
"Unordered list": "Μη ταξινομημένη λίστα",
|
||||
"Unpublish note": "Αποδημοσίευση σημείωσης",
|
||||
"Unshare": "Κατάργηση κοινής χρήσης",
|
||||
"Unshare this notebook? The recipients will no longer have access to its content.": "Διακόψτε την κοινή χρήση σε αυτό το σημειωματάριο; Οι παραλήπτες δεν θα έχουν πλέον πρόσβαση στο περιεχόμενό του.",
|
||||
@@ -864,21 +985,25 @@
|
||||
"Upgrade the sync target to the latest version.": "Αναβαθμίστε το στόχο συγχρονισμού στην πιο πρόσφατη έκδοση.",
|
||||
"URL": "URL",
|
||||
"Usage: %s": "Χρήση: %s",
|
||||
"Use biometrics to secure access to the app": "Χρησιμοποιήστε βιομετρικά στοιχεία για να διασφαλίσετε την πρόσβαση στην εφαρμογή",
|
||||
"Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE": "Χρησιμοποιήστε τη μορφή μακράς λίστας. Η μορφή είναι ID, NOTE_COUNT (για σημειωματάριο), DATE, TODO_CHECKED (για to-dos), TITLE",
|
||||
"Use spell checker": "Χρήση ορθογραφικού ελέγχου",
|
||||
"Use the arrows and page up/down to scroll the lists and text areas (including this console).": "Χρησιμοποιήστε τα βελάκια πατώντας πάνω/κάτω για να μετακινηθείτε στις λίστες και τις περιοχές κειμένου (συμπεριλαμβανομένης αυτής της κονσόλας).",
|
||||
"Use the arrows to move the layout items. Press \"Escape\" to exit.": "Χρησιμοποιήστε τα βέλη για να μετακινήσετε τα στοιχεία διάταξης. Πατήστε \"Escape\" για έξοδο.",
|
||||
"Use this to rebuild the search index if there is a problem with search. It may take a long time depending on the number of notes.": "Χρησιμοποιήστε το για να ξαναφτιάξετε το ευρετήριο αναζήτησης, εάν υπάρχει πρόβλημα με την αναζήτηση. Μπορεί να χρειαστεί πολύς χρόνος ανάλογα με τον αριθμό των σημειώσεων.",
|
||||
"Use your biometrics to secure access to your application. You can always set it up later in Settings.": "Χρησιμοποιήστε τα βιομετρικά σας στοιχεία για να εξασφαλίσετε την πρόσβαση στην εφαρμογή σας. Μπορείτε πάντα να το ρυθμίσετε αργότερα στις Ρυθμίσεις.",
|
||||
"Used for most text in the markdown editor. If not found, a generic proportional (variable width) font is used.": "Χρησιμοποιείται για το μεγαλύτερο μέρος του κειμένου στο πρόγραμμα επεξεργασίας σημειώσεων. Εάν δεν βρεθεί, χρησιμοποιείται μια γενική αναλογική γραμματοσειρά (μεταβλητού πλάτους).",
|
||||
"Used where a fixed width font is needed to lay out text legibly (e.g. tables, checkboxes, code). If not found, a generic monospace (fixed width) font is used.": "Χρησιμοποιείται όταν απαιτείται γραμματοσειρά σταθερού πλάτους για την ευανάκριβη δημιουργία κειμένου (π.χ. πίνακες, πλαίσια ελέγχου, κωδικός). Εάν δεν βρεθεί, χρησιμοποιείται μια γενική μονοδιάστημα (σταθερού πλάτους).",
|
||||
"User deletions": "Διαγραφές χρήστη",
|
||||
"Users": "Χρήστες",
|
||||
"Valid": "Έγκυρo",
|
||||
"Verify your identity": "Επαληθεύστε την ταυτότητα σας",
|
||||
"View": "Προβολή",
|
||||
"View on map": "Προβολή στο χάρτη",
|
||||
"View them now": "Προβολή τώρα",
|
||||
"Viewer": "Εμφάνιση",
|
||||
"Vim": "Vim",
|
||||
"Voice typing...": "Φωνητική πληκτρολόγηση...",
|
||||
"Warning": "Προειδοποίηση",
|
||||
"Warning: not all resources shown for performance reasons (limit: %s).": "Προειδοποίηση: δεν εμφανίζονται όλοι οι πόροι για λόγους απόδοσης (όριο:% s).",
|
||||
"Web Clipper": "Web Clipper",
|
||||
@@ -888,6 +1013,7 @@
|
||||
"WebDAV username": "WebDAV username",
|
||||
"Website and documentation": "Ιστοσελίδα και εγχειρίδια",
|
||||
"Welcome to Joplin!\n\nType `:help shortcuts` for the list of keyboard shortcuts, or just `:help` for usage information.\n\nFor example, to create a notebook press `mb`; to create a note press `mn`.": "Καλώς ήλθατε στο Joplin!\n\nΠληκτρολογίστε `:help shortcuts` για τη λίστα συντομεύσεων πληκτρολογίου ή απλά `:help` για πληροφορίες χρήσης.\n\nΓια παράδειγμα, για να δημιουργήσετε ένα σημειωματάριο πατήστε `mb` ενώ για να δημιουργήσετε μια σημείωση πατήστε `mn`.",
|
||||
"Welcome!": "Καλώς ήρθατε!",
|
||||
"When creating a new note:": "Κατά τη δημιουργία μιας νέας σημείωσης:",
|
||||
"When creating a new to-do:": "Κατά τη δημιουργία ενός νέου to-do:",
|
||||
"Words": "Λέξεις",
|
||||
@@ -902,6 +1028,7 @@
|
||||
"You may use the tool below to re-encrypt your data, for example if you know that some of your notes are encrypted with an obsolete encryption method.": "Μπορείτε να χρησιμοποιήσετε το παρακάτω εργαλείο για να κρυπτογραφήσετε εκ νέου τα δεδομένα σας, για παράδειγμα, εάν γνωρίζετε ότι ορισμένες από τις σημειώσεις σας είναι κρυπτογραφημένες με μια παρωχημένη μέθοδο κρυπτογράφησης.",
|
||||
"Your choice: ": "Η επιλογή σας: ",
|
||||
"Your data is going to be re-encrypted and synced again.": "Τα δεδομένα σας πρόκειται να κρυπτογραφηθούν και να συγχρονιστούν ξανά.",
|
||||
"Your password is needed to decrypt some of your data.": "Ο κωδικός πρόσβασής σας είναι απαραίτητος για την αποκρυπτογράφηση ορισμένων δεδομένων σας.",
|
||||
"Your password is needed to decrypt some of your data. Type `:e2ee decrypt` to set it.": "Ο κωδικός πρόσβασής σας είναι απαραίτητος για την αποκρυπτογράφηση ορισμένων δεδομένων σας. Πληκτρολογήστε `:e2ee decrypt` για να τον ορίσετε.",
|
||||
"Your permission to use your camera is required.": "Απαιτείται η άδειά σας για τη χρήση της φωτογραφικής σας μηχανής.",
|
||||
"Your version: %s": "Η έκδοσή σου: %s",
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
"Accelerator \"%s\" is not valid.": "Le raccourci \"%s\" n'est pas valide.",
|
||||
"Accelerator \"%s\" is used for \"%s\" and \"%s\" commands. This may lead to unexpected behaviour.": "Le raccourci \"%s\" est utilisé par les commandes \"%s\" et \"%s\", ce qui peut causer des problèmes.",
|
||||
"Accept": "Accepter",
|
||||
"Access denied: Please check your username and password": "Accès non-autorisé : Veuillez vérifier votre nom et mot de passe",
|
||||
"Access denied: Please re-enter your password and/or username": "Accès non-autorisé : Veuillez ré-entrer votre nom ou mot de passe",
|
||||
"Account": "Compte",
|
||||
"Action": "Action",
|
||||
"Actions": "Actions",
|
||||
@@ -72,6 +74,7 @@
|
||||
"Ambiguous notebook \"%s\". Please use notebook id instead - press \"ti\" to see the short notebook id or use $b for current selected notebook": "Titre ambigu \"%s\". Veuillez entrer l'identifiant du carnet - pressez \"ti\" pour afficher les identifiants, ou utilisez $b pour le carnet en cours",
|
||||
"Ambiguous notebook \"%s\". Please use short notebook id instead - press \"ti\" to see the short notebook id": "Titre ambigu \"%s\". Veuillez entrer l'identifiant du carnet - pressez \"ti\" pour afficher les identifiants",
|
||||
"An update is available, do you want to download it now?": "Une mise à jour est disponible, souhaitez vous la télécharger maintenant ?",
|
||||
"Any email sent to this address will be converted into a note and added to your collection. The note will be saved into the Inbox notebook": "Un email envoyé à cette adresse sera converti en note et ajouté à votre collection. La note sera sauvé dans votre carnet \"Inbox\"",
|
||||
"Appearance": "Apparence",
|
||||
"Application": "Application",
|
||||
"Apply": "Appliquer",
|
||||
@@ -105,6 +108,8 @@
|
||||
"Browse...": "Parcourir…",
|
||||
"Bulleted List": "Liste à puces",
|
||||
"Can Share": "Peut partager",
|
||||
"Can view": "Lecture seule",
|
||||
"Can view and edit": "Lecture et édition",
|
||||
"Cancel": "Annuler",
|
||||
"Cancelling background synchronisation... Please wait.": "Annulation de la synchronisation… Veuillez patienter.",
|
||||
"Cancelling...": "Annulation…",
|
||||
@@ -112,6 +117,7 @@
|
||||
"Cannot access %s": "Impossible d'accéder à %s",
|
||||
"Cannot change encrypted item": "Un objet chiffré ne peut pas être modifié",
|
||||
"Cannot copy note to \"%s\" notebook": "Impossible de copier la note vers le carnet \"%s\"",
|
||||
"Cannot create a new note: %s": "Impossible de créer une nouvelle note : %s",
|
||||
"Cannot find \"%s\".": "Impossible de trouver \"%s\".",
|
||||
"Cannot find: \"%s\"": "Impossible de trouver : \"%s\"",
|
||||
"Cannot initialise synchroniser.": "Impossible d'initialiser la synchronisation.",
|
||||
@@ -179,6 +185,7 @@
|
||||
"Copy Markdown link": "Copier lien Markdown",
|
||||
"Copy path to clipboard": "Copier le chemin",
|
||||
"Copy Shareable Link": "Copier lien partageable",
|
||||
"Copy to clipboard": "Copier",
|
||||
"Copy token": "Copier le code",
|
||||
"Could not authorise application:\n\n%s\n\nPlease try again.": "Impossible d'autoriser le logiciel :\n\n%s\n\nVeuillez réessayer.",
|
||||
"Could not connect to Joplin Server. Please check the Synchronisation options in the config screen. Full error was:\n\n%s": "Impossible de se connecter au server Joplin. Veuillez vérifier la configuration. L'erreur complète était :\n\n%s",
|
||||
@@ -234,13 +241,16 @@
|
||||
"Delete expired tokens": "Supprimer les tokens expirés",
|
||||
"Delete line": "Supprimer la ligne",
|
||||
"Delete local data and re-download from sync target": "Supprimer les données locales et re‑télécharger depuis la cible de synchronisation",
|
||||
"Delete note": "Supprimer la note",
|
||||
"Delete note \"%s\"?": "Supprimer note \"%s\" ?",
|
||||
"Delete note?": "Supprimer la note ?",
|
||||
"Delete notebook": "Supprimer le carnet",
|
||||
"Delete notebook \"%s\"?\n\nAll notes and sub-notebooks within this notebook will also be deleted.": "Effacer le carnet \"%s\" ?\n\nToutes les notes et sous‑carnets dans ce carnet seront également effacés.",
|
||||
"Delete notebook? All notes and sub-notebooks within this notebook will also be deleted.": "Effacer le carnet ? Toutes les notes et sous‑carnets dans ce carnet seront également effacés.",
|
||||
"Delete plugin \"%s\"?": "Supprimer plugin \"%s\" ?",
|
||||
"Delete profile \"%s\"": "Supprimer profil \"%s\" ?",
|
||||
"Delete selected notes": "Supprimer les notes sélectionnées",
|
||||
"Delete the Inbox notebook?\n\nIf you delete the inbox notebook, any email that's recently been sent to it may be lost.": "Supprimer le carnet \"Inbox\" ?\n\nSi vous le supprimez, tout email qui lui a été récemment envoyé peut être perdu.",
|
||||
"Delete these %d notes?": "Supprimer ces %d notes ?",
|
||||
"Delete this invitation? The recipient will no longer have access to this shared notebook.": "Supprimer cette invitation ? Le destinataire n'aura plus accès au carnet partagé.",
|
||||
"Delete this profile?": "Supprimer ce profil ?",
|
||||
@@ -307,6 +317,8 @@
|
||||
"Either \"text\" or \"json\"": "Soit \"text\" soit \"json\"",
|
||||
"Emacs": "Emacs",
|
||||
"Email": "Email",
|
||||
"Email to note": "Conversion email en note",
|
||||
"Email to Note": "Conversion email en note",
|
||||
"Emails": "Emails",
|
||||
"emphasised text": "texte en italique",
|
||||
"Enable": "Activer",
|
||||
@@ -360,11 +372,14 @@
|
||||
"Expand": "Ouvrir",
|
||||
"Export": "Exporter",
|
||||
"Export all": "Tout exporter",
|
||||
"Export all notes as JEX": "Exporter toutes les notes en JEX",
|
||||
"Export debug report": "Exporter rapport de débogage",
|
||||
"Export Debug Report": "Exporter rapport de débogage",
|
||||
"Export profile": "Exporter le profil",
|
||||
"Exported successfully!": "Exporté avec succès !",
|
||||
"Exporting profile...": "Exportation du profil…",
|
||||
"Exporting to \"%s\" as \"%s\" format. Please wait...": "Exportation en cours vers \"%s\" au format \"%s\". Veuillez patienter…",
|
||||
"Exporting...": "Exportation...",
|
||||
"Exports Joplin data to the given path. By default, it will export the complete database including notebooks, notes, tags and resources.": "Exporter les données de Joplin. Par défaut, la base de donnée complète sera exportée, y compris les carnets, notes, tags et ressources.",
|
||||
"Exports only the given note.": "Exporter uniquement la note spécifiée.",
|
||||
"Exports only the given notebook.": "Exporter uniquement le carnet spécifié.",
|
||||
@@ -770,6 +785,7 @@
|
||||
"Set the password": "Définir le mot de passe",
|
||||
"Sets the property <name> of the given <note> to the given [value]. Possible properties are:\n\n%s": "Assigner la valeur [value] à la propriété <name> de la <note> donnée. Les valeurs possibles sont :\n\n%s",
|
||||
"Share": "Partager",
|
||||
"Share a copy of all notes in a file format that can be imported by Joplin on a computer.": "Partager une copie de toutes vos notes dans un format qui peut être importé par Joplin sur un ordinateur.",
|
||||
"Share and collaborate on a notebook": "Partager et collaborer sur un carnet",
|
||||
"Share Notebook": "Partager le carnet",
|
||||
"Share notebook...": "Partager carnet…",
|
||||
@@ -915,6 +931,9 @@
|
||||
"This attachment is not downloaded or not decrypted yet.": "Cette pièce jointe n'est pas téléchargée ou pas encore déchiffrée.",
|
||||
"This authorisation token is only needed to allow third-party applications to access Joplin.": "Ce code d'authentification est nécessaire uniquement pour permettre aux logiciels tiers d'accéder aux données de Joplin.",
|
||||
"This is an advanced tool to show the attachments that are linked to your notes. Please be careful when deleting one of them as they cannot be restored afterwards.": "Ceci est un outil pour lister les fichiers qui sont attachés à vos notes. Veuillez noter que lorsqu'un fichier est supprimé ici, il ne peut pas être restauré par la suite.",
|
||||
"This note could not be deleted: %s": "Cette note n'a pas pu être supprimée : %s",
|
||||
"This note could not be duplicated: %s": "Cette note n'a pas pu être dupliquée : %s",
|
||||
"This note could not be moved: %s": "Cette note n'a pas pu être déplacée : %s",
|
||||
"This note does not have geolocation information.": "Cette note n'a pas d'information de géolocalisation.",
|
||||
"This note has been modified:": "Cette note a été modifiée :",
|
||||
"This note has no content. Click on \"%s\" to toggle the editor and edit the note.": "Cette note n'a pas de contenu. Cliquer sur \"%s\" pour basculer vers l'éditeur et éditer cette note.",
|
||||
@@ -962,6 +981,7 @@
|
||||
"Type a note title or part of its content to jump to it. Or type # followed by a tag name, or @ followed by a notebook name. Or type : to search for commands.": "Entrez le titre d’une note, ou entrez # suivi du nom d’une étiquette, ou @ suivi du nom d’un carnet. Ou entrez : pour chercher une commande.",
|
||||
"Type new tags or select from list": "Entrez de nouvelles étiquettes ou sélectionnez de la liste",
|
||||
"Type: %s.": "Type : %s.",
|
||||
"Unable to export or share data. Reason: %s": "Impossible d'exporter les données : %s",
|
||||
"Uncompleted to-dos on top": "Tâches non‑terminées en haut",
|
||||
"Undo": "Annuler",
|
||||
"Unknown flag: %s": "Paramètre inconnu : %s",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Voice typing...": "Saisie vocale...",
|
||||
"Warning": "Avertissement",
|
||||
"Warning: not all resources shown for performance reasons (limit: %s).": "Attention : tous les fichiers ne sont pas affichés pour des raisons de performance (limite : %s).",
|
||||
"Warnings:\n%s": "Avertissements:\n%s",
|
||||
"Web Clipper": "Web Clipper",
|
||||
"WebDAV": "WebDAV",
|
||||
"WebDAV password": "WebDAV : Mot de passe",
|
||||
|
||||
@@ -280,6 +280,7 @@
|
||||
"Downloaded and decrypted": "Preuzeto i dešifrirano",
|
||||
"Downloaded and encrypted": "Preuzeto i šifrirano",
|
||||
"Downloading": "Preuzimanje",
|
||||
"Downloading %s language files...": "Preuzimanje jezičnih datoteka za %s …",
|
||||
"Downloading resources...": "Preuzimanje resursa …",
|
||||
"Dracula": "Drakula",
|
||||
"Drop notes or files here": "Ispusti bilješke ili dokumente ovdje",
|
||||
@@ -410,6 +411,7 @@
|
||||
"Headers": "Zaglavlja",
|
||||
"Heading": "Naslov",
|
||||
"Help": "Pomoć",
|
||||
"Hermes enabled: %d": "Hermes aktiviran: %d",
|
||||
"Hide %s": "Sakrij %s",
|
||||
"Hide advanced": "Sakrij napredne",
|
||||
"Hide disabled": "Sakrij deaktivirane",
|
||||
@@ -493,6 +495,7 @@
|
||||
"Later": "Kasnije",
|
||||
"Layout": "Raspored",
|
||||
"Layout button sequence": "Slijed gumbova rasporeda",
|
||||
"Leave it blank to download the language files from the default website": "Ostavi prazno za preuzimanje jezičnih datoteka sa standardne web stranice",
|
||||
"Leave notebook...": "Napusti bilježnicu …",
|
||||
"Legal": "Legal",
|
||||
"Letter": "Letter",
|
||||
@@ -716,7 +719,7 @@
|
||||
"Replace": "Zamijeni",
|
||||
"Replace all": "Zamijeni sve",
|
||||
"Replace with...": "Zamijeni sa …",
|
||||
"Replace: ": "Zamijeni:",
|
||||
"Replace: ": "Zamijeni: ",
|
||||
"Reset application layout": "Obnovi raspored programa",
|
||||
"Reset master password": "Obnovi glavnu lozinku",
|
||||
"Resources: %d.": "Resursi: %d.",
|
||||
@@ -757,6 +760,7 @@
|
||||
"Select all": "Označi sve",
|
||||
"Select emoji...": "Odaberi emoji …",
|
||||
"Select file...": "Odaberi datoteku …",
|
||||
"Select parent notebook": "Obriši nadređenu bilježnicu",
|
||||
"Server is already running on port %d": "Poslužitelj je već pokrenut na priključku %d",
|
||||
"Server is not running.": "Poslužitelj ne radi.",
|
||||
"Server is running on port %d": "Poslužitelj se pokreće na priključku %d",
|
||||
@@ -1002,7 +1006,8 @@
|
||||
"View them now": "Pogledaj ih sada",
|
||||
"Viewer": "Preglednik",
|
||||
"Vim": "Vim",
|
||||
"Voice typing...": "Tipkanje glasa …",
|
||||
"Voice typing language files (URL)": "Jezične datoteke za tipkanje glasom (URL)",
|
||||
"Voice typing...": "Tipkanje glasom …",
|
||||
"Warning": "Upozorenje",
|
||||
"Warning: not all resources shown for performance reasons (limit: %s).": "Upozorenje: za brže izvođenje, ne prikazuju se svi resursi (ograničenje: %s).",
|
||||
"Web Clipper": "Web Clipper",
|
||||
@@ -1012,6 +1017,7 @@
|
||||
"WebDAV username": "WebDAV korisničko ime",
|
||||
"Website and documentation": "Web-stranica i dokumentacija",
|
||||
"Welcome to Joplin!\n\nType `:help shortcuts` for the list of keyboard shortcuts, or just `:help` for usage information.\n\nFor example, to create a notebook press `mb`; to create a note press `mn`.": "Dobro došao, dobro došla u Joplin!\n\nUpiši `:help shortcuts` za popis tipkovnih prečaca ili samo`:help` za informacije o korištenju.\n\nNa primjer, za stvaranje bilježnice pritisni `mb`; za stvaranje bilješke pritisni `mn`.",
|
||||
"Welcome!": "Dobro došao, dobro došla!",
|
||||
"When creating a new note:": "Prilikom stvaranja nove bilješke:",
|
||||
"When creating a new to-do:": "Prilikom stvaranja novog zadatka:",
|
||||
"Words": "Broj riječi",
|
||||
|
||||
@@ -41,45 +41,45 @@ locales['uk_UA'] = require('./uk_UA.json');
|
||||
locales['vi'] = require('./vi.json');
|
||||
locales['zh_CN'] = require('./zh_CN.json');
|
||||
locales['zh_TW'] = require('./zh_TW.json');
|
||||
stats['ar'] = {"percentDone":79};
|
||||
stats['ar'] = {"percentDone":77};
|
||||
stats['eu'] = {"percentDone":22};
|
||||
stats['bs_BA'] = {"percentDone":57};
|
||||
stats['bg_BG'] = {"percentDone":45};
|
||||
stats['ca'] = {"percentDone":88};
|
||||
stats['hr_HR'] = {"percentDone":99};
|
||||
stats['cs_CZ'] = {"percentDone":98};
|
||||
stats['da_DK'] = {"percentDone":98};
|
||||
stats['bs_BA'] = {"percentDone":56};
|
||||
stats['bg_BG'] = {"percentDone":44};
|
||||
stats['ca'] = {"percentDone":86};
|
||||
stats['hr_HR'] = {"percentDone":98};
|
||||
stats['cs_CZ'] = {"percentDone":96};
|
||||
stats['da_DK'] = {"percentDone":96};
|
||||
stats['de_DE'] = {"percentDone":98};
|
||||
stats['et_EE'] = {"percentDone":44};
|
||||
stats['et_EE'] = {"percentDone":43};
|
||||
stats['en_GB'] = {"percentDone":100};
|
||||
stats['en_US'] = {"percentDone":100};
|
||||
stats['es_ES'] = {"percentDone":97};
|
||||
stats['es_ES'] = {"percentDone":95};
|
||||
stats['eo'] = {"percentDone":25};
|
||||
stats['fi_FI'] = {"percentDone":98};
|
||||
stats['fi_FI'] = {"percentDone":96};
|
||||
stats['fr_FR'] = {"percentDone":100};
|
||||
stats['gl_ES'] = {"percentDone":29};
|
||||
stats['id_ID'] = {"percentDone":88};
|
||||
stats['it_IT'] = {"percentDone":80};
|
||||
stats['hu_HU'] = {"percentDone":77};
|
||||
stats['nl_BE'] = {"percentDone":78};
|
||||
stats['nl_NL'] = {"percentDone":87};
|
||||
stats['nb_NO'] = {"percentDone":87};
|
||||
stats['fa'] = {"percentDone":54};
|
||||
stats['pl_PL'] = {"percentDone":89};
|
||||
stats['pt_BR'] = {"percentDone":87};
|
||||
stats['pt_PT'] = {"percentDone":72};
|
||||
stats['ro'] = {"percentDone":50};
|
||||
stats['sl_SI'] = {"percentDone":79};
|
||||
stats['sv'] = {"percentDone":99};
|
||||
stats['th_TH'] = {"percentDone":36};
|
||||
stats['vi'] = {"percentDone":77};
|
||||
stats['tr_TR'] = {"percentDone":99};
|
||||
stats['uk_UA'] = {"percentDone":71};
|
||||
stats['el_GR'] = {"percentDone":87};
|
||||
stats['ru_RU'] = {"percentDone":99};
|
||||
stats['sr_RS'] = {"percentDone":64};
|
||||
stats['zh_CN'] = {"percentDone":96};
|
||||
stats['zh_TW'] = {"percentDone":88};
|
||||
stats['gl_ES'] = {"percentDone":28};
|
||||
stats['id_ID'] = {"percentDone":86};
|
||||
stats['it_IT'] = {"percentDone":78};
|
||||
stats['hu_HU'] = {"percentDone":75};
|
||||
stats['nl_BE'] = {"percentDone":76};
|
||||
stats['nl_NL'] = {"percentDone":86};
|
||||
stats['nb_NO'] = {"percentDone":85};
|
||||
stats['fa'] = {"percentDone":53};
|
||||
stats['pl_PL'] = {"percentDone":88};
|
||||
stats['pt_BR'] = {"percentDone":85};
|
||||
stats['pt_PT'] = {"percentDone":70};
|
||||
stats['ro'] = {"percentDone":49};
|
||||
stats['sl_SI'] = {"percentDone":78};
|
||||
stats['sv'] = {"percentDone":97};
|
||||
stats['th_TH'] = {"percentDone":35};
|
||||
stats['vi'] = {"percentDone":75};
|
||||
stats['tr_TR'] = {"percentDone":97};
|
||||
stats['uk_UA'] = {"percentDone":98};
|
||||
stats['el_GR'] = {"percentDone":97};
|
||||
stats['ru_RU'] = {"percentDone":97};
|
||||
stats['sr_RS'] = {"percentDone":63};
|
||||
stats['zh_CN'] = {"percentDone":98};
|
||||
stats['zh_TW'] = {"percentDone":86};
|
||||
stats['ja_JP'] = {"percentDone":88};
|
||||
stats['ko'] = {"percentDone":88};
|
||||
stats['ko'] = {"percentDone":86};
|
||||
module.exports = { locales: locales, stats: stats };
|
||||
@@ -1,8 +1,10 @@
|
||||
{
|
||||
"\"%s\" is missing the required \"%s\" property.": "\"%s\" は必須の \"%s\" プロパティを持っていません。",
|
||||
"%d days": "%d 日",
|
||||
"%d GB": "%d GB",
|
||||
"%d hour": "%d 時間",
|
||||
"%d hours": "%d 時間",
|
||||
"%d MB": "%d MB",
|
||||
"%d minutes": "%d 分",
|
||||
"%d notes match this pattern. Delete them?": "%d 個のノートが一致しました。削除しますか?",
|
||||
"%s %s (%s, %s)": "%s %s (%s, %s)",
|
||||
@@ -55,6 +57,7 @@
|
||||
"Admin dashboard": "管理者ダッシュボード",
|
||||
"Advanced options": "詳細な設定",
|
||||
"Advanced tools": "高度なツール",
|
||||
"All data, including notes, notebooks and tags will be permanently deleted.": "ノート、ノートブック、タグを含むすべてのデータが完全に削除されます。",
|
||||
"All notes": "すべてのノート",
|
||||
"All potential ports are in use - please report the issue at %s": "使用候補のポートはすべて利用中です - 問題を %s に報告してください",
|
||||
"Also displays unset and hidden config variables.": "未設定または非表示の設定項目も表示します。",
|
||||
@@ -67,6 +70,7 @@
|
||||
"Are you sure you want to renew the authorisation token?": "認証トークンを更新してもよろしいですか?",
|
||||
"Arguments:": "引数:",
|
||||
"Aritim Dark": "Aritim Dark",
|
||||
"Attach": "添付",
|
||||
"Attach file": "ファイルを添付する",
|
||||
"Attach photo": "写真を添付",
|
||||
"Attach...": "添付...",
|
||||
@@ -214,6 +218,7 @@
|
||||
"Delete plugin \"%s\"?": "プラグイン \"%s\" を削除しますか?",
|
||||
"Delete these %d notes?": "これら %d のノートを削除しますか?",
|
||||
"Delete this invitation? The recipient will no longer have access to this shared notebook.": "この招待を削除しますか? 削除後は招待の受信者がこの共有ノートブックにアクセスできなくなります。",
|
||||
"Delete this profile?": "このプロファイルを削除しますか?",
|
||||
"Deleted local items: %d.": "ローカルアイテムの削除: %d.",
|
||||
"Deleted remote items: %d.": "リモートアイテムの削除: %d.",
|
||||
"Deletes the given notebook.": "指定されたノートブックを削除します。",
|
||||
@@ -259,8 +264,10 @@
|
||||
"Duplicates the notes matching <note> to [notebook]. If no notebook is specified the note is duplicated in the current notebook.": "<note>に一致するノートを[notebook]に複製します。[notebook]が指定されていない場合は、現在のノートブックに複製を行います。",
|
||||
"Edit": "編集",
|
||||
"Edit in external editor": "外部エディターで編集",
|
||||
"Edit link": "リンクの編集",
|
||||
"Edit note.": "ノートを編集する。",
|
||||
"Edit notebook": "ノートブックの編集",
|
||||
"Edit profile": "プロファイルを編集",
|
||||
"Edit profile configuration...": "プロファイル設定を編集...",
|
||||
"Editor": "エディター",
|
||||
"Editor font": "エディターのフォント",
|
||||
@@ -292,6 +299,7 @@
|
||||
"Enable note history": "ノートの履歴を有効にする",
|
||||
"Enable PDF viewer": "PDFビューアーを有効にする",
|
||||
"Enable soft breaks": "ソフトブレークを有効にする",
|
||||
"Enable spellcheck in the text editor": "テキストエディタでスペルチェックを有効にする",
|
||||
"Enable table of contents extension": "目次拡張を有効にする",
|
||||
"Enable typographer support": "Typographer(記号文字)を有効にする",
|
||||
"Enable video player": "動画プレーヤーを有効にする",
|
||||
@@ -368,6 +376,7 @@
|
||||
"Hide %s": "%s を隠す",
|
||||
"Hide disabled keys": "無効化したキーを表示しない",
|
||||
"Hide Joplin": "Joplinを隠す",
|
||||
"Hide keyboard": "キーボードを隠す",
|
||||
"Highlight": "ハイライト",
|
||||
"Home": "ホーム",
|
||||
"Horizontal Rule": "横線",
|
||||
@@ -398,6 +407,7 @@
|
||||
"Inline Code": "インラインコード",
|
||||
"Insert": "挿入線",
|
||||
"Insert Hyperlink": "ハイパーリンクの挿入",
|
||||
"Insert time": "日時の挿入",
|
||||
"Install": "インストール",
|
||||
"Install from file": "ファイルからインストール",
|
||||
"Installed": "インストール済み",
|
||||
@@ -428,6 +438,7 @@
|
||||
"Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.": "Joplin WebクリッパーはブラウザーからWebページとスクリーンショットをJoplinへ保存します。",
|
||||
"Joplin website": "JoplinのWebサイト",
|
||||
"Joplin's own sync service. Also gives access to Joplin-specific features such as publishing notes or collaborating on notebooks with others.": "Joplin独自の同期サービスです。特定ノートの公開や共有ノートブック上での共同作業などJoplin固有の機能も利用可能です。",
|
||||
"KaTeX": "KaTeX",
|
||||
"Keep note history for": "ノート履歴の保存期間",
|
||||
"Keyboard Mode": "キーバインド",
|
||||
"Keyboard Shortcut": "ショートカットキー",
|
||||
@@ -461,6 +472,7 @@
|
||||
"Make a donation": "寄付する",
|
||||
"Manage master password": "マスターパスワードの管理",
|
||||
"Manage master password...": "マスターパスワードの管理...",
|
||||
"Manage profiles": "プロファイルの管理",
|
||||
"Manage your plugins": "プラグインを管理",
|
||||
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, `status`, `decrypt-file`, and `target-status`.": "エンドツーエンド暗号化(E2EE)の設定コマンドです。`enable`, `disable`, `decrypt`, `status`, `decrypt-file`, `target-status` があります。",
|
||||
"Manual": "手動",
|
||||
@@ -551,6 +563,7 @@
|
||||
"Only one note can be printed at a time.": "一度に印刷できるノートは1つだけです。",
|
||||
"Open": "開く",
|
||||
"Open %s": "%s を開く",
|
||||
"Open PDF viewer": "PDFビューアーを開く",
|
||||
"Open profile directory": "プロファイルディレクトリを開く",
|
||||
"Open Sync Wizard...": "同期ウィザードを開く...",
|
||||
"Open...": "開く...",
|
||||
@@ -566,6 +579,7 @@
|
||||
"Password:": "パスワード:",
|
||||
"Passwords do not match!": "パスワードが一致しません!",
|
||||
"Paste": "貼り付け",
|
||||
"Paste as text": "テキストとして貼り付け",
|
||||
"Path:": "パス:",
|
||||
"PDF File": "PDF ファイル",
|
||||
"Permission needed": "許可が必要",
|
||||
@@ -603,8 +617,10 @@
|
||||
"Process oversized accounts": "容量オーバーのアカウントを処理する",
|
||||
"Process user deletions": "ユーザー削除を実施する",
|
||||
"Profile": "プロファイル",
|
||||
"Profile name": "プロファイル名",
|
||||
"Profile name:": "プロファイル名:",
|
||||
"Profile Version: %s": "プロファイルバージョン: %s",
|
||||
"Profiles": "プロファイル",
|
||||
"Properties": "プロパティ",
|
||||
"Public-private key pair:": "公開鍵・秘密鍵ペア:",
|
||||
"Publish note...": "ノートを公開...",
|
||||
@@ -622,6 +638,7 @@
|
||||
"Recipients:": "受信者:",
|
||||
"Redo": "やり直す",
|
||||
"Refresh": "更新",
|
||||
"Regular expression": "正規表現",
|
||||
"Reject": "拒否",
|
||||
"Remove": "削除",
|
||||
"Remove tag \"%s\" from all notes?": "すべてのノートからタグ \"%s\" を削除しますか?",
|
||||
@@ -631,6 +648,7 @@
|
||||
"Rename tag:": "タグの変更:",
|
||||
"Renames the given <item> (note or notebook) to <name>.": "<item> (ノートまたはノートブック)の名前を、<name>に変更します。",
|
||||
"Renew token": "トークンを更新する",
|
||||
"Reset application layout": "画面レイアウトをリセット",
|
||||
"Reset master password": "マスターパスワードをリセット",
|
||||
"Resources: %d.": "リソース: %d.",
|
||||
"Restart and upgrade": "再起動してアップグレード",
|
||||
@@ -798,6 +816,7 @@
|
||||
"The web clipper service is not enabled.": "Webクリッパーサービスは有効になっていません。",
|
||||
"Theme": "テーマ",
|
||||
"There are currently no notes. Create one by clicking on the (+) button.": "ノートがありません。(+)ボタンを押して新しいノートを作成してください。",
|
||||
"There are unsaved changes.": "保存されていない変更があります。",
|
||||
"There is currently no notebook. Create one by clicking on \"New notebook\".": "ノートブックがありません。新しいノートブックを作成してください。",
|
||||
"There is no data to export.": "エクスポートするデータがありません。",
|
||||
"There was a [conflict](%s) on the attachment below.\n\n%s": "下記の添付ファイルで[衝突](%s)が発生しました。\n\n%s",
|
||||
@@ -892,6 +911,8 @@
|
||||
"View them now": "今すぐ表示",
|
||||
"Viewer": "ビューアー",
|
||||
"Vim": "Vim",
|
||||
"Voice typing language files (URL)": "音声入力言語ファイル (URL)",
|
||||
"Voice typing...": "音声入力…",
|
||||
"Warning": "警告",
|
||||
"Warning: not all resources shown for performance reasons (limit: %s).": "注意: 性能上の理由により、リソースは最大 %s 件までしか表示されません。",
|
||||
"Web Clipper": "Webクリッパー",
|
||||
|
||||
@@ -280,6 +280,7 @@
|
||||
"Downloaded and decrypted": "Загружено и расшифровано",
|
||||
"Downloaded and encrypted": "Загружено и зашифровано",
|
||||
"Downloading": "Загрузка",
|
||||
"Downloading %s language files...": "Загрузка %s языковые файлы..",
|
||||
"Downloading resources...": "Загрузка ресурсов...",
|
||||
"Dracula": "Дракула",
|
||||
"Drop notes or files here": "Перетащите сюда заметки или файлы",
|
||||
@@ -410,6 +411,7 @@
|
||||
"Headers": "Заголовки",
|
||||
"Heading": "Заголовок",
|
||||
"Help": "Помощь",
|
||||
"Hermes enabled: %d": "Hermes включен: %d",
|
||||
"Hide %s": "Скрыть %s",
|
||||
"Hide advanced": "Скрыть расширенные",
|
||||
"Hide disabled": "Скрыть отключенный",
|
||||
@@ -757,6 +759,7 @@
|
||||
"Select all": "Выбрать все",
|
||||
"Select emoji...": "Выбрать эмодзи...",
|
||||
"Select file...": "Выбрать файл...",
|
||||
"Select parent notebook": "Выбрать родительский блокнот",
|
||||
"Server is already running on port %d": "Сервер уже запущен. Порт: %d",
|
||||
"Server is not running.": "Сервер не запущен.",
|
||||
"Server is running on port %d": "Сервер запущен. Порт: %d",
|
||||
@@ -1002,6 +1005,7 @@
|
||||
"View them now": "Просмотреть сейчас",
|
||||
"Viewer": "Просмотрщик",
|
||||
"Vim": "Vim",
|
||||
"Voice typing language files (URL)": "Языковые файлы голосового набора (URL)",
|
||||
"Voice typing...": "Голосовой набор...",
|
||||
"Warning": "Предупреждение",
|
||||
"Warning: not all resources shown for performance reasons (limit: %s).": "Предупреждение: не все данные показаны по соображениям производительности (ограничение:%s).",
|
||||
@@ -1012,6 +1016,7 @@
|
||||
"WebDAV username": "Имя пользователя WebDAV",
|
||||
"Website and documentation": "Сайт и документация",
|
||||
"Welcome to Joplin!\n\nType `:help shortcuts` for the list of keyboard shortcuts, or just `:help` for usage information.\n\nFor example, to create a notebook press `mb`; to create a note press `mn`.": "Добро пожаловать в Joplin!\n\nВведите `:help shortcuts` для просмотра списка клавиатурных сочетаний или просто `:help` для просмотра справочной информации.\n\nНапример, для создания блокнота введите `mb`, для создания заметки - `mn`.",
|
||||
"Welcome!": "Добро пожаловать!",
|
||||
"When creating a new note:": "При создании новой заметки:",
|
||||
"When creating a new to-do:": "При создании новой задачи:",
|
||||
"Words": "Cлова",
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
"Active": "Aktif",
|
||||
"Actual Size": "Asıl Boyut",
|
||||
"Add body": "Gövde Ekle",
|
||||
"Add new": "Yeni bir şey ekle: ",
|
||||
"Add new": "Yeni bir şey ekle",
|
||||
"Add or remove tags:": "Etiket ekle veya kaldır:",
|
||||
"Add recipient:": "Alıcı ekle:",
|
||||
"Add title": "Başlık ekle",
|
||||
@@ -377,7 +377,7 @@
|
||||
"File system": "Dosya sistemi",
|
||||
"Filter tags": "Etikerleri filtrele",
|
||||
"Find and replace": "Bul ve değiştir",
|
||||
"Find: ": "Ara:",
|
||||
"Find: ": "Ara: ",
|
||||
"Firefox Extension": "Firefox Eklentisi",
|
||||
"Fix search index": "Arama indeksini düzelt",
|
||||
"Fixing search index...": "Arama indeksi düzeltiliyor...",
|
||||
@@ -410,6 +410,7 @@
|
||||
"Headers": "Başlıklar",
|
||||
"Heading": "Başlık",
|
||||
"Help": "Yardım",
|
||||
"Hermes enabled: %d": "Hermes aktif edildi: %d",
|
||||
"Hide %s": "Şunu Gizle: %s",
|
||||
"Hide advanced": "Gelişmiş'leri gizle",
|
||||
"Hide disabled": "İptal edilmişleri gizle",
|
||||
@@ -716,7 +717,7 @@
|
||||
"Replace": "Değiştir",
|
||||
"Replace all": "Tümünü değiştir",
|
||||
"Replace with...": "Şununla değiştir...",
|
||||
"Replace: ": "Değiştir:",
|
||||
"Replace: ": "Değiştir: ",
|
||||
"Reset application layout": "Ugulama görünümünü sıfırla",
|
||||
"Reset master password": "Ana parolayı sıfırla",
|
||||
"Resources: %d.": "Kaynaklar: %d.",
|
||||
@@ -757,6 +758,7 @@
|
||||
"Select all": "Tümünü seç",
|
||||
"Select emoji...": "Emoji seç...",
|
||||
"Select file...": "Dosya seç...",
|
||||
"Select parent notebook": "Ana not defterini seç",
|
||||
"Server is already running on port %d": "Sunucu zaten %d portunda çalışıyor",
|
||||
"Server is not running.": "Sunucu çalışmıyor.",
|
||||
"Server is running on port %d": "Sunucu %d portunda çalışıyor",
|
||||
@@ -874,7 +876,7 @@
|
||||
"The default admin password is insecure and has not been changed! [Change it now](%s)": "Varsayılan admin parolası güvenli değil ve de henüz güncellenmedi! [Şimdi güncelle](%s)",
|
||||
"The default encryption method has been changed to a more secure one and it is recommended that you apply it to your data.": "Varsayılan şifreleme yolu daha güvenli bir yola güncellendi, bu sebeple tüm verinizi yeniden şifrelemenizi öneriyoruz.",
|
||||
"The default encryption method has been changed, you should re-encrypt your data.": "Varsayılan şifreleme yolu daha güvenli bir yola güncellendi, bu sebeple tüm verinizi yeniden şifrelemelisiniz.",
|
||||
"The default profile cannot be deleted": "Varsayılan profil silinemez.",
|
||||
"The default profile cannot be deleted": "Varsayılan profil silinemez",
|
||||
"The editor command (may include arguments) that will be used to open a note. If none is provided it will try to auto-detect the default editor.": "Editör komutu (argüman içerebilir) not açmak için kullanılacaktır. Eğer sağlanmadıysa, varsayılan düzenleyiciyi otomatik olarak algılamaya çalışır.",
|
||||
"The factor property sets how the item will grow or shrink to fit the available space in its container with respect to the other items. Thus an item with a factor of 2 will take twice as much space as an item with a factor of 1.Restart app to see changes.": "Faktör özelliği, dosyanın diğer dosyaların da ebatına sadık kalarak yeterli alan olduğu sürece hangi değerle büyüyüp ufalacağını tanımlar. Faktör değeri 2 olan bir bileşen, faktör değeri 1 olana nazaran 2 kat fazla alan kaplar. Değişiklikleri görmek için uygulamayı yeniden başlatın.",
|
||||
"The following attachments are being watched for changes:": "Şu ek dosyaları değişiklikler için izlenmekte:",
|
||||
@@ -1012,6 +1014,7 @@
|
||||
"WebDAV username": "WebDAV kullanıcı adı",
|
||||
"Website and documentation": "Web sitesi ve dökümanlar",
|
||||
"Welcome to Joplin!\n\nType `:help shortcuts` for the list of keyboard shortcuts, or just `:help` for usage information.\n\nFor example, to create a notebook press `mb`; to create a note press `mn`.": "Joplin'e Hoş Geldiniz!\n\nKlavye kısayollarının listesi için `:help shortcuts` yazın veya kullanım bilgileri için sadece `:help` yazın.\n\nÖrneğin, bir not defteri oluşturmak için `mb`; Bir not oluşturmak için `mn` tuşuna basın.",
|
||||
"Welcome!": "Hoş Geldiniz!",
|
||||
"When creating a new note:": "Yeni bir not oluştururken:",
|
||||
"When creating a new to-do:": "Yeni bir yapılacak oluşturulurken:",
|
||||
"Words": "Kelime",
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"\"%s\" is missing the required \"%s\" property.": "У “%s” відсутня необхідна властивість “%s”.",
|
||||
"%d days": "%d днів",
|
||||
"%d GB": "%d ГБ",
|
||||
"%d GB storage space": "%d ГБ місця для зберігання",
|
||||
"%d hour": "%d година",
|
||||
"%d hours": "%d годин",
|
||||
"%d MB": "%d MБ",
|
||||
"%d MB per note or attachment": "%d МБ на нотатку або вкладення",
|
||||
"%d minutes": "%d хвилин",
|
||||
"%d notes match this pattern. Delete them?": "%d нотаток відповідають цьому шаблону. Видалити їх?",
|
||||
"%s": "%s",
|
||||
"%s %s (%s, %s)": "%s %s (%s, %s)",
|
||||
"%s (%s) could not be uploaded: %s": "Не вдалося завантажити %s (%s): %s",
|
||||
"%s (%s) would like to share a notebook with you.": "%s (%s) хоче поділитись нотаткою з вами.",
|
||||
@@ -27,6 +32,8 @@
|
||||
"&Tools": "&Інструменти",
|
||||
"&View": "&Перегляд",
|
||||
"(%s)": "(%s)",
|
||||
"(In plugin: %s)": "(У плагіні: %s)",
|
||||
"(None)": "(Жодного)",
|
||||
"(wysiwyg: %s)": "(wysiwyg: %s)",
|
||||
"- Camera: to allow taking a picture and attaching it to a note.": "- Камера: щоб надати доступ до камери була можливість додавати фто до нотатки.",
|
||||
"- Location: to allow attaching geo-location information to a note.": "- Розташування: щоб дозволити додавати інформацію про геолокацію до нотатки.",
|
||||
@@ -41,32 +48,43 @@
|
||||
"Accelerator \"%s\" is not valid.": "Прискорювач “%s” хибний.",
|
||||
"Accelerator \"%s\" is used for \"%s\" and \"%s\" commands. This may lead to unexpected behaviour.": "Прискорювач “%s” використовується для команд “%s” та “%s”. Це може призвести до несподіваної поведінки.",
|
||||
"Accept": "Прийняти",
|
||||
"Account": "Обліковий запис",
|
||||
"Action": "Дія",
|
||||
"Actions": "Дії",
|
||||
"Active": "Активний",
|
||||
"Actual Size": "Фактичний розмір",
|
||||
"Add body": "Додати тіло",
|
||||
"Add new": "Додати нове",
|
||||
"Add or remove tags:": "Додати або видалити теги:",
|
||||
"Add recipient:": "Додати одержувача",
|
||||
"Add recipient:": "Додати одержувача:",
|
||||
"Add title": "Додати заголовок",
|
||||
"Add to dictionary": "Додати до словника",
|
||||
"Admin": "Адміністратор",
|
||||
"Admin dashboard": "Панель адміністратора",
|
||||
"Advanced options": "Розширені опції",
|
||||
"Advanced tools": "Розширені інструменти",
|
||||
"All data, including notes, notebooks and tags will be permanently deleted.": "Усі дані, включно з нотатками, блокнотами та тегами, буде остаточно видалено.",
|
||||
"All notes": "Всі нотатки",
|
||||
"All potential ports are in use - please report the issue at %s": "Усі потенційні порти використовуються - повідомте про проблему на %s",
|
||||
"Also displays unset and hidden config variables.": "Також відображає невстановлені та приховані змінні конфігурації.",
|
||||
"Also publish linked notes": "Також опублікувати пов’язані нотатки",
|
||||
"Always": "Завжди",
|
||||
"Ambiguous notebook \"%s\". Please use notebook id instead - press \"ti\" to see the short notebook id or use $b for current selected notebook": "Неоднозначний блокнот \"%s\". Натомість використовуйте ідентифікатор блокнота - натисніть \"ti\", щоб побачити короткий ідентифікатор блокнота, або використовуйте $b для поточного вибраного блокнота",
|
||||
"Ambiguous notebook \"%s\". Please use short notebook id instead - press \"ti\" to see the short notebook id": "Неоднозначний блокнот \"%s\". Натомість використовуйте короткий ідентифікатор блокнота - натисніть \"ti\", щоб побачити короткий ідентифікатор блокнота",
|
||||
"An update is available, do you want to download it now?": "Доступне оновлення, ви хочете завантажити його зараз?",
|
||||
"Appearance": "Зовнішній вигляд",
|
||||
"Application": "Застосунок",
|
||||
"Apply": "Застосувати",
|
||||
"Are you sure you want to renew the authorisation token?": "Ви впевненні що хочете поновити токен авторизації?",
|
||||
"Are you sure you want to return to the default layout? The current layout configuration will be lost.": "Ви впевнені, що хочете повернутися до макета за замовчуванням? Поточну конфігурацію макета буде втрачено.",
|
||||
"Arguments:": "Параметри:",
|
||||
"Aritim Dark": "Aritim Dark",
|
||||
"Attach": "Прикріпити",
|
||||
"Attach file": "Прикріпити файл",
|
||||
"Attach photo": "Прикріпити фото",
|
||||
"Attach...": "Прикріпити…",
|
||||
"Attaches the given file to the note.": "Додає даний файл до нотатки.",
|
||||
"attachment": "вкладення",
|
||||
"Attachment conflict: \"%s\"": "Конфлікт вкладення: “%s”",
|
||||
"Attachment download behaviour": "Поведінка завантаження вкладення",
|
||||
"Attachments": "Вкладення",
|
||||
@@ -75,13 +93,18 @@
|
||||
"Authentication was not completed (did not receive an authentication token).": "Автентифікація не була завершена (не отримано токен автентифікації).",
|
||||
"Authorisation token:": "Токен авторизації:",
|
||||
"Auto": "Авто",
|
||||
"Auto-add disabled accounts for deletion": "Автоматично додавати вимкнені облікові записи для видалення",
|
||||
"Auto-pair braces, parenthesis, quotations, etc.": "Автоматичне закриття дужок, лапок тощо.",
|
||||
"Automatically check for updates": "Автоматично перевіряти наявність оновлень",
|
||||
"Automatically switch theme to match system theme": "Автоматично перемикати тему на відповідну системній темі",
|
||||
"Back": "Назад",
|
||||
"Basic": "Основні",
|
||||
"Biometric unlock is not setup on the device. Please set it up in order to unlock Joplin. If the device is on lockout, consider switching it off and on to reset biometrics scanning.": "На пристрої не налаштовано біометричне розблокування. Налаштуйте його, щоб розблокувати Joplin. Якщо пристрій заблоковано, вимкніть і ввімкніть його, щоб скинути біометричне сканування.",
|
||||
"Bold": "Жирний",
|
||||
"Browse all plugins": "Переглянути всі розширення",
|
||||
"Browse...": "Переглянути…",
|
||||
"Bulleted List": "Маркований список",
|
||||
"Can Share": "Може поділитися",
|
||||
"Cancel": "Скасувати",
|
||||
"Cancelling background synchronisation... Please wait.": "Скасування фонової синхронізації … Зачекайте.",
|
||||
"Cancelling...": "Скасування…",
|
||||
@@ -90,12 +113,17 @@
|
||||
"Cannot change encrypted item": "Не вдається змінити зашифрований елемент",
|
||||
"Cannot copy note to \"%s\" notebook": "Не можливо скопіювати нотатку до “%s” блокнота",
|
||||
"Cannot find \"%s\".": "Не вдається знайти “%s”.",
|
||||
"Cannot find: \"%s\"": "Не вдається знайти “%s”",
|
||||
"Cannot initialise synchroniser.": "Не вдається ініціалізувати синхронізатор.",
|
||||
"Cannot load \"%s\" module for format \"%s\" and output \"%s\"": "Не вдається завантажити модуль “%s” для формату “%s” і вивести “%s”",
|
||||
"Cannot load \"%s\" module for format \"%s\" and target \"%s\"": "Не вдається завантажити модуль “%s” для формату “%s” і цілі “%s”",
|
||||
"Cannot move note to \"%s\" notebook": "Не можливо перемістити нотатку до “%s” блокнота",
|
||||
"Cannot move notebook to this location": "Не можливо перемістити блокнот в дану локацію",
|
||||
"Cannot refresh token: authentication data is missing. Starting the synchronisation again may fix the problem.": "Не вдається оновити токен: дані автентифікації відсутні. Повторний запуск синхронізації може вирішити проблему.",
|
||||
"Cannot save %s \"%s\" because it is larger than the allowed limit (%s)": "Неможливо зберегти %s \"%s\", оскільки він перевищує дозволений ліміт (%s)",
|
||||
"Cannot save %s \"%s\" because it would go over the total allowed size (%s) for this account": "Неможливо зберегти %s \"%s\", оскільки він перевищить загальний дозволений розмір (%s) для цього облікового запису",
|
||||
"Cannot share encrypted notebook with recipient %s because they have not enabled end-to-end encryption. They may do so from the screen Configuration > Encryption.": "Неможливо надати доступ до зашифрованого блокнота одержувачу %s, оскільки він не ввімкнув наскрізне шифрування. Вони можуть зробити це на екрані Конфігурація > Шифрування.",
|
||||
"Case sensitive": "З урахуванням регістру",
|
||||
"Change application layout": "Змінити макет програми",
|
||||
"Change language": "Змінити мову",
|
||||
"Characters": "Символи",
|
||||
@@ -113,28 +141,40 @@
|
||||
"Click to add tags...": "Клацніть, щоб додати теги...",
|
||||
"Client ID: %s": "ID клієнта: %s",
|
||||
"Close": "Закрити",
|
||||
"Close dropdown": "Закрити випадаючий список",
|
||||
"Close Window": "Закрити вікно",
|
||||
"Code": "Код",
|
||||
"Code Block": "Блок коду",
|
||||
"Code View": "Вбудований код",
|
||||
"Collaborate on notebooks with others": "Співпрацюйте над нотатками з іншими",
|
||||
"Collapse": "Згорнути",
|
||||
"Coming alarms": "Найближчі будильники",
|
||||
"Comma-separated list of paths to directories to load the certificates from, or path to individual cert files. For example: /my/cert_dir, /other/custom.pem. Note that if you make changes to the TLS settings, you must save your changes before clicking on \"Check synchronisation configuration\".": "Розділений комами список шляхів до каталогів, з яких завантажуються сертифікати, або шлях до окремих файлів сертифіката. Наприклад: /my/cert_dir, /other/custom.pem. Зверніть увагу, що якщо ви вносите зміни до налаштувань TLS, потрібно зберегти зміни, перш ніж натискати “Перевірити конфігурацію синхронізації”.",
|
||||
"command": "команда",
|
||||
"Command": "Команда",
|
||||
"Command palette": "Панель команд",
|
||||
"Command palette...": "Панель команд...",
|
||||
"Completed": "Завершено",
|
||||
"Completed decryption.": "Завершено розшифрування.",
|
||||
"Completed: %s (%s)": "Завершено: %s (%s)",
|
||||
"Compress old changes": "Стиснути старі зміни",
|
||||
"Configuration": "Налаштування",
|
||||
"Confirm password cannot be empty": "Підтвердження паролю не може бути порожнім",
|
||||
"Confirm password:": "Підтвердіть пароль:",
|
||||
"Confirmation": "Підтвердження",
|
||||
"Conflicted: %d": "Конфліктів: %d",
|
||||
"Conflicts": "Конфлікти",
|
||||
"Conflicts (attachments)": "Конфлікти (вкладення)",
|
||||
"Consolidated billing": "Консолідована оплата",
|
||||
"Content provided by %s": "Вміст надано %s",
|
||||
"Continue": "Продовжити",
|
||||
"Convert to note": "Перетворити на нотатку",
|
||||
"Convert to todo": "Перетворити на список справ",
|
||||
"Converting speech to text...": "Перетворення голос на текст...",
|
||||
"Copy": "Копіювати",
|
||||
"Copy dev mode command to clipboard": "Скопіюйте команду режиму розробника в буфер обміну",
|
||||
"Copy external link": "Копіювати зовнішнє посилання",
|
||||
"Copy image": "Копіювати зображення",
|
||||
"Copy Link Address": "Копіювати адресу посилання",
|
||||
"Copy Markdown link": "Скопіювати Markdown посилання",
|
||||
"Copy path to clipboard": "Копіювати шлях до буфера обміну",
|
||||
@@ -142,15 +182,26 @@
|
||||
"Copy token": "Скопіювати токен",
|
||||
"Could not authorise application:\n\n%s\n\nPlease try again.": "Не вдалося авторизувати додаток:\n\n%s\n\nБудь ласка, спробуйте ще раз.",
|
||||
"Could not connect to Joplin Server. Please check the Synchronisation options in the config screen. Full error was:\n\n%s": "Не вдалося підключитися до сервера Joplin. Будь ласка, перевірте параметри синхронізації на екрані налаштування. Повна помилка:\n\n%s",
|
||||
"Could not connect to plugin repository.": "Не вдалося підключитися до репозиторію плагінів.",
|
||||
"Could not export notes: %s": "Не вдалося експортувати примітки: %s",
|
||||
"Could not install plugin: %s": "Не можливо встановити розширення: %s",
|
||||
"Could not respond to the invitation. Please try again, or check with the notebook owner if they are still sharing it.\n\nThe error was: \"%s\"": "Не вдалося відповісти на запрошення. Будь ласка, спробуйте ще раз або зверніться до власника блокнота, чи він все ще надає до нього спільний доступ.\n\nВиникла наступна помилка:\"%s\"",
|
||||
"Could not switch profile: %s": "Не вдалося змінити профіль: %s",
|
||||
"Could not upgrade master key: %s": "Не вдалося оновити головний ключ: %s",
|
||||
"Could not verify the share status of this notebook - aborting. Please try again when you are connected to the internet.": "Не вдалося перевірити статус спільного використання цього блокнота – перериваю. Спробуйте ще раз, коли Ви підключитесь до Інтернету.",
|
||||
"Could not verify your identify: %s": "Не вдалося підтвердити Вашу особу: %is",
|
||||
"Create": "Створити",
|
||||
"Create a new notebook under a parent notebook.": "Створіть новий блокнот під батьківським блокнотом.",
|
||||
"Create a notebook": "Створити блокнот",
|
||||
"Create new profile...": "Створити новий профіль...",
|
||||
"Create notebook": "Створити блокнот",
|
||||
"Create user": "Створити користувача",
|
||||
"Created": "Створено",
|
||||
"created date": "дата створення",
|
||||
"Created local items: %d.": "Створено локальних елементів: %d.",
|
||||
"Created locally": "Створено локально",
|
||||
"Created remote items: %d.": "Створено віддалених елементів: %d.",
|
||||
"Created: ": "Створено: ",
|
||||
"Created: %d.": "Створено: %d.",
|
||||
"Created: %s": "Створено: %s",
|
||||
"Creates a new note.": "Створює нову нотатку.",
|
||||
@@ -166,8 +217,12 @@
|
||||
"Custom TLS certificates": "Спеціальні сертифікати TLS",
|
||||
"Cut": "Вирізати",
|
||||
"Dark": "Dark",
|
||||
"Dashboard": "Панель керування",
|
||||
"Database v%s": "База даних v%s",
|
||||
"Date": "Дата",
|
||||
"Date format": "Формат дати",
|
||||
"days": "днів",
|
||||
"Decrease indent level": "Зменшити відступ",
|
||||
"Decrypted items: %d": "Розшифровано елементів: %d",
|
||||
"Decrypted items: %s / %s": "Розшифровано елементів: %s / %s",
|
||||
"Decrypting items: %d/%d": "Дешифрування елементів: %d/%d",
|
||||
@@ -175,13 +230,20 @@
|
||||
"Default: %s": "За замовчуванням: %s",
|
||||
"Delete": "Видалити",
|
||||
"Delete attachment \"%s\"?": "Видалити вкладення “%s”?",
|
||||
"Delete expired sessions": "Видалити сесії, термін дії яких закінчився",
|
||||
"Delete expired tokens": "Видаліть прострочені токени",
|
||||
"Delete line": "Видалити лінію",
|
||||
"Delete local data and re-download from sync target": "Видаліть локальні дані та повторно завантажте з цілі синхронізації",
|
||||
"Delete note \"%s\"?": "Видалити нотатку “%s”?",
|
||||
"Delete note?": "Видалити нотатку?",
|
||||
"Delete notebook \"%s\"?\n\nAll notes and sub-notebooks within this notebook will also be deleted.": "Видалити блокнот “%s”?\n\nУсі нотатки та блокноти в цьому блокноті також будуть видалені.",
|
||||
"Delete notebook? All notes and sub-notebooks within this notebook will also be deleted.": "Видалити блокнот? Усі нотатки та блокноти в цьому блокноті також будуть видалені.",
|
||||
"Delete plugin \"%s\"?": "Видалити розширення “%s”?",
|
||||
"Delete profile \"%s\"": "Видалити профіль \"%s\"",
|
||||
"Delete selected notes": "Видалити вибрані нотатки",
|
||||
"Delete these %d notes?": "Видалити ці %d нотаток?",
|
||||
"Delete this invitation? The recipient will no longer have access to this shared notebook.": "Видалити це запрошення? Одержувач більше не матиме доступу до цього спільного блокнота.",
|
||||
"Delete this profile?": "Видалити цей профіль?",
|
||||
"Deleted local items: %d.": "Видалено локальних елементів: %d.",
|
||||
"Deleted remote items: %d.": "Видалено віддалених елементів: %d.",
|
||||
"Deletes the given notebook.": "Видаляє даний блокнот.",
|
||||
@@ -191,7 +253,9 @@
|
||||
"Destination format: %s": "Формат призначення: %s",
|
||||
"Directory": "Каталог",
|
||||
"Directory to synchronise with (absolute path)": "Каталог для синхронізації (абсолютний шлях)",
|
||||
"Disable": "Відключити",
|
||||
"Disable encryption": "Вимкнути шифрування",
|
||||
"Disable safe mode and restart": "Вимкніть безпечний режим і перезапустіть",
|
||||
"Disable Web Clipper Service": "Відключити сервіс Web Clipper",
|
||||
"Disabled": "Відключено",
|
||||
"Disabling encryption means *all* your notes and attachments are going to be re-synchronised and sent unencrypted to the sync target. Do you wish to continue?": "Вимкнення шифрування означає, що *всі* ваші нотатки та вкладення будуть повторно синхронізовані та відправлені незашифрованими до цілі синхронізації. Ви хочете продовжити?",
|
||||
@@ -208,29 +272,42 @@
|
||||
"Displays version information": "Відображає інформацію про версію",
|
||||
"Do it now": "Зробити зараз",
|
||||
"Do not ask for confirmation.": "Не питати підтвердження.",
|
||||
"Do not lose the password as, for security purposes, this will be the *only* way to decrypt the data! To enable encryption, please enter your password below.": "Не втрачайте пароль, оскільки з міркувань безпеки це буде *єдиний* спосіб розшифрувати дані! Щоб увімкнути шифрування, введіть свій пароль нижче.",
|
||||
"Done": "Готово",
|
||||
"Download": "Завантажити",
|
||||
"Download and install the relevant extension for your browser:": "Завантажте та встановіть відповідне розширення для вашого браузера:",
|
||||
"Downloaded": "Завантажено",
|
||||
"Downloaded and decrypted": "Завантажено і розшифровано",
|
||||
"Downloaded and encrypted": "Завантадено і зашифровано",
|
||||
"Downloading": "Завантаження",
|
||||
"Downloading %s language files...": "Завантаження мовних файлів %s...",
|
||||
"Downloading resources...": "Завантаження ресурсів…",
|
||||
"Dracula": "Dracula",
|
||||
"Drop notes or files here": "Перетягніть сюди нотатки або файли",
|
||||
"Dropbox": "Dropbox",
|
||||
"Dropbox Login": "Dropbox логін",
|
||||
"Duplicate": "Дублікат",
|
||||
"Duplicate line": "Продублювати рядок",
|
||||
"Duplicate selected notes": "Продублювати вибрані нотатки",
|
||||
"Duplicates the notes matching <note> to [notebook]. If no notebook is specified the note is duplicated in the current notebook.": "Дублює нотатки, що відповідають <note> на [notebook]. Якщо блокнот не вказаний, нотатка дублюється в поточному блокноті.",
|
||||
"Edit": "Редагувати",
|
||||
"Edit in external editor": "Радктувати в зовнішньому редакторі",
|
||||
"Edit link": "Редагувати посилання",
|
||||
"Edit note.": "Редагувати примітку.",
|
||||
"Edit notebook": "Редагувати блокнот",
|
||||
"Edit profile": "Редагувати профіль",
|
||||
"Edit profile configuration...": "Редагувати конфігурацію профілю...",
|
||||
"Editor": "Редактор",
|
||||
"Editor font": "Шрифт редактора",
|
||||
"Editor font family": "Сімейство шрифтів редактора",
|
||||
"Editor font size": "Розмір шрифту редактора",
|
||||
"Editor maximum width": "Максимальна ширина редактора",
|
||||
"Editor monospace font family": "Редактор сімейства моноширинних шрифтів",
|
||||
"Editor: %s": "Редактор: %s",
|
||||
"Either \"text\" or \"json\"": "Або “текст”, або “json”",
|
||||
"Emacs": "Emacs",
|
||||
"Email": "Електронна пошта",
|
||||
"Emails": "Електронні поштові адреси",
|
||||
"emphasised text": "підкреслення",
|
||||
"Enable": "Ввімкнути",
|
||||
"Enable ++insert++ syntax": "Увімкнути ++insert++ синтаксис",
|
||||
@@ -238,6 +315,7 @@
|
||||
"Enable ^sup^ syntax": "Увімкнути ^sup^ синтаксис",
|
||||
"Enable abbreviation syntax": "Уімвнути синтаксис абревіатур",
|
||||
"Enable audio player": "Увімкнути аудіо-плеєр",
|
||||
"Enable biometrics authentication?": "Увімкнути біометричну автентифікацію?",
|
||||
"Enable deflist syntax": "Увімкнути синтаксис “визначень”",
|
||||
"Enable encryption": "Ввімкнути шифрування",
|
||||
"Enable footnotes": "Увімкнути виноски",
|
||||
@@ -250,17 +328,23 @@
|
||||
"Enable note history": "Увімкнути історію нотаток",
|
||||
"Enable PDF viewer": "Увімкнути переглядач PDF",
|
||||
"Enable soft breaks": "Увімкнути м’які переходи",
|
||||
"Enable spellcheck in the text editor": "Увімкніть перевірку правопису в текстовому редакторі",
|
||||
"Enable table of contents extension": "Увімкнути розширення змісту",
|
||||
"Enable the Markdown toolbar": "Увімкніть панель інструментів Markdown",
|
||||
"Enable typographer support": "Увімкнути підтримку типографічних символів",
|
||||
"Enable video player": "Увімкнути відео-плеєр",
|
||||
"Enable Web Clipper Service": "Ввімкнути Web Clipper сервіс",
|
||||
"Enable ~sub~ syntax": "Увімкнути ~sub~ синтаксис",
|
||||
"Enabled": "Включено",
|
||||
"Enabling encryption means *all* your notes and attachments are going to be re-synchronised and sent encrypted to the sync target.": "Увімкнення шифрування означає, що *всі* ваші нотатки та вкладені файли будуть повторно синхронізовані та надіслані в зашифрованому вигляді на ціль синхронізації.",
|
||||
"Encrypted": "Зашифровано",
|
||||
"Encrypted items cannot be modified": "Зашифровані елементи не можуть бути змінені",
|
||||
"Encryption": "Шифрування",
|
||||
"Encryption Config": "Налаштування шифрування",
|
||||
"Encryption is: %s": "Шифрування: %s",
|
||||
"Encryption keys": "Ключі шифрування",
|
||||
"Encryption:": "Шифрування:",
|
||||
"End-to-end encryption": "Наскрізне шифрування",
|
||||
"Enter code here": "Введіть код тут",
|
||||
"Enter master password:": "Введіть головний пароль:",
|
||||
"Enter notebook title": "Редагувати заголовок блокнота",
|
||||
@@ -269,11 +353,14 @@
|
||||
"Error opening note in editor: %s": "Помилка відкриття нотатки в редакторі: %s",
|
||||
"Error. Please check that URL, username, password, etc. are correct and that the sync target is accessible. The reported error was:": "Помилка. Переконайтесь, що URL-адреса, ім’я користувача, пароль тощо є правильними та ціль синхронізації доступна. Повідомлення про помилку:",
|
||||
"Error: %s": "Помилка: %s",
|
||||
"Errors only": "Лише помилки",
|
||||
"Evernote Export File (as HTML)": "Evernote Export File (as HTML)",
|
||||
"Evernote Export File (as Markdown)": "Evernote Export File (as Markdown)",
|
||||
"Exits the application.": "Вийти із програми.",
|
||||
"Expand": "Розгорнути",
|
||||
"Export": "Експорт",
|
||||
"Export all": "Експортувати все",
|
||||
"Export debug report": "Експорт звіту про налагодження",
|
||||
"Export Debug Report": "Експортувати розширений звіт",
|
||||
"Export profile": "Експорт профілю",
|
||||
"Exporting profile...": "Експортування профілю…",
|
||||
@@ -284,10 +371,14 @@
|
||||
"Fail-safe": "Безаварійність",
|
||||
"Fail-safe: Do not wipe out local data when sync target is empty (often the result of a misconfiguration or bug)": "Безаварійність: не видаляйти локальні дані, коли ціль синхронізації порожня (часто результат неправильної конфігурації або помилки)",
|
||||
"Fatal error:": "Критична помилка:",
|
||||
"Feature flags": "Функціональні прапорці",
|
||||
"Fetched items: %d/%d.": "Отримано елементів: %d/%d.",
|
||||
"Fetching resources: %d/%d": "Завантаження ресурсів: %d/%d",
|
||||
"File": "Файл",
|
||||
"File system": "Файлова система",
|
||||
"Filter tags": "Фільтри тегів",
|
||||
"Find and replace": "Знайти та замінити",
|
||||
"Find: ": "Знайти: ",
|
||||
"Firefox Extension": "Рощширення Firefox",
|
||||
"Fix search index": "Виправлення індексу пошуку",
|
||||
"Fixing search index...": "Виправлення індексу пошуку…",
|
||||
@@ -296,29 +387,50 @@
|
||||
"Focus title": "Фокус на залоговку",
|
||||
"Folders": "Каталоги",
|
||||
"For debugging purpose only: export your profile to an external SD card.": "Тільки для налагодження: експортуйте свій профіль на зовнішню SD-карту.",
|
||||
"For example \"%s\"": "Наприклад \"%s\"",
|
||||
"For information on how to customise the shortcuts please visit %s": "Щоб отримати інформацію про те, як налаштувати скорочення клавіатури, відвідайте %s",
|
||||
"For more information about End-To-End Encryption (E2EE) and advice on how to enable it please check the documentation:": "Щоб отримати додаткову інформацію про наскрізне шифрування (E2EE) та поради щодо його ввімкнення, перегляньте документацію:",
|
||||
"For the list of keyboard shortcuts and config options, type `help keymap`": "Для списку комбінацій клавіш та параметрів конфігурації введіть `help keymap`",
|
||||
"Force path style": "Примусовий стиль шляху",
|
||||
"Formatting": "Форматування",
|
||||
"Forward": "Вперед",
|
||||
"Found: %d.": "Знайдено: %d.",
|
||||
"FTS enabled: %d": "FTS увімкнено: %d",
|
||||
"Full changelog": "Повний журнал змін",
|
||||
"Full name": "Повне ім'я",
|
||||
"General": "Загальні",
|
||||
"Generated": "Згенерований",
|
||||
"Generating link...": "Генерування посиланя…",
|
||||
"Get it now:": "Отримати зараз:",
|
||||
"Get pre-releases when checking for updates": "Отримуйте ntcnjdb випуски, перевіряючи наявність оновлень",
|
||||
"Gets or sets a config value. If [value] is not provided, it will show the value of [name]. If neither [name] nor [value] is provided, it will list the current configuration.": "Отримує або встановлює значення конфігурації. Якщо значення [value] не вказано, воно буде відображати значення [name]. Якщо не вказано ні [ім’я], ні [значення], у ньому буде вказано поточну конфігурацію.",
|
||||
"Go to source URL": "Перейти до посилання",
|
||||
"Goto Anything...": "Перейти будь-куди…",
|
||||
"Grant authorisation": "Надати дозвіл",
|
||||
"Header %d": "Заголовок %d",
|
||||
"Headers": "Заголовоки",
|
||||
"Heading": "Заголовок",
|
||||
"Help": "Допомога",
|
||||
"Hermes enabled: %d": "Hermes увімкнено: %d",
|
||||
"Hide %s": "Сховати %s",
|
||||
"Hide advanced": "Приховати розширені",
|
||||
"Hide disabled": "Приховати вимкнено",
|
||||
"Hide disabled keys": "Приховати вимкнені клавіші",
|
||||
"Hide Joplin": "Сховати Joplin",
|
||||
"Hide keyboard": "Сховати клавіатуру",
|
||||
"Hide more actions": "Приховати інші дії",
|
||||
"Highlight": "Виділення",
|
||||
"Home": "Головна",
|
||||
"Horizontal Rule": "Горизонтальна лінія",
|
||||
"HTML Directory": "HTML Directory",
|
||||
"HTML File": "HTML File",
|
||||
"Hyperlink": "Посилання",
|
||||
"Icon": "Іконка",
|
||||
"ID": "ID",
|
||||
"Idle": "Бездіяльність",
|
||||
"Ignore": "Ігнорувати",
|
||||
"Ignore TLS certificate errors": "Ігнорувати помилки сертифіката TLS",
|
||||
"Images": "Зображення",
|
||||
"Import": "Імпорт",
|
||||
"Importing from \"%s\" as \"%s\" format. Please wait...": "Імпортування з “%s” в форматі “%s”. Будь ласка, зачекайте…",
|
||||
"Importing notes...": "Імпортування нотаток…",
|
||||
@@ -331,11 +443,14 @@
|
||||
"In order to use the web clipper, you need to do the following:": "Для того, щоб використовувати web clipper, вам потрібно виконати наступне:",
|
||||
"In progress": "В процесі",
|
||||
"In: %s": "У: %s",
|
||||
"Increase indent level": "Збільшити відступ",
|
||||
"Indent less": "Зменшити відступ",
|
||||
"Indent more": "Збільшити відступ",
|
||||
"Information": "Інформація",
|
||||
"Inline Code": "Вбудований код",
|
||||
"Insert": "Вставити",
|
||||
"Insert Hyperlink": "Вставити Посилання",
|
||||
"Insert time": "Введіть час",
|
||||
"Install": "Встановити",
|
||||
"Install from file": "Встановити з файла",
|
||||
"Installed": "Встановлено",
|
||||
@@ -345,58 +460,98 @@
|
||||
"Invalid answer: %s": "Хибна відповідь: %s",
|
||||
"Invalid command: \"%s\"": "Хибна команда: “%s”",
|
||||
"Invalid option value: \"%s\". Possible values are: %s.": "Недійсне значення параметра: “%s”. Можливі значення: %s.",
|
||||
"Invalid password": "Невірний пароль",
|
||||
"Italic": "Курсив",
|
||||
"Item \"%s\" could not be downloaded: %s": "Не вдалося завантажити елемент “%s”: %s",
|
||||
"Items": "Елементи",
|
||||
"Items that cannot be decrypted": "Елементи, які неможливо розшифрувати",
|
||||
"Items that cannot be synchronised": "Елементи, які неможливо синхронізувати",
|
||||
"Join us on Twitter": "Приєднуйтесь до нас у Twitter",
|
||||
"Joplin can synchronise your notes using various providers. Select one from the list below.": "Joplin може синхронізувати ваші нотатки за допомогою різних провайдерів. Виберіть один зі списку нижче.",
|
||||
"Joplin Cloud": "Joplin Cloud",
|
||||
"Joplin Cloud email": "Електронна пошта Joplin Cloud",
|
||||
"Joplin Cloud password": "Пароль Joplin Cloud",
|
||||
"Joplin Export Directory": "Joplin Export Directory",
|
||||
"Joplin Export File": "Joplin Export File",
|
||||
"Joplin failed to decrypt these items multiple times, possibly because they are corrupted or too large. These items will remain on the device but Joplin will no longer attempt to decrypt them.": "Joplin не зміг розшифрувати ці елементи кілька разів, можливо, тому, що вони пошкоджені або занадто великі. Ці елементи залишаться на пристрої, але Joplin більше не намагатиметься їх розшифрувати.",
|
||||
"Joplin Forum": "Форум Joplin",
|
||||
"Joplin Server": "Joplin Server",
|
||||
"Joplin Server email": "Електронна пошта Joplin Server",
|
||||
"Joplin Server password": "Joplin Server пароль",
|
||||
"Joplin Server URL": "Joplin Server посилання",
|
||||
"Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.": "Joplin Web Clipper дозволяє зберігати веб-сторінки та знімки екрана з вашого браузера в Joplin.",
|
||||
"Joplin website": "Веб-сайт Joplin",
|
||||
"Joplin's own sync service. Also gives access to Joplin-specific features such as publishing notes or collaborating on notebooks with others.": "Власна служба синхронізації Joplin. Також надає доступ до специфічних для Joplin функцій, як-от публікація нотаток або спільна робота над блокнотами з іншими.",
|
||||
"KaTeX": "KaTeX",
|
||||
"Keep note history for": "Зберігайте історію нотаток протягом",
|
||||
"Keyboard Mode": "Режим клавіатури",
|
||||
"Keyboard Shortcut": "Комбінація клавіш",
|
||||
"Keyboard Shortcuts": "Скорочення клавіатури",
|
||||
"Keychain Supported: %s": "Підтримка Keychain: %s",
|
||||
"Keys that need upgrading": "Ключі, які потребують оновлення",
|
||||
"Landscape": "Горизонтально",
|
||||
"Language": "Мова",
|
||||
"Last error: %s": "Остання помилка: %s",
|
||||
"Later": "Пізніше",
|
||||
"Layout": "Макет",
|
||||
"Layout button sequence": "Послідовність кнопок макета",
|
||||
"Leave it blank to download the language files from the default website": "Залиште це поле пустим, щоб завантажити мовні файли з веб-сайту за замовчуванням",
|
||||
"Leave notebook...": "Залишити блокнот...",
|
||||
"Legal": "Legal",
|
||||
"Letter": "Letter",
|
||||
"Light": "Light",
|
||||
"Lines": "Стрічки",
|
||||
"Link": "Посилання",
|
||||
"Link description": "Опис посилання",
|
||||
"Link has been copied to clipboard!": "Посилання скопійовано в буфер обміну!",
|
||||
"Link text": "Текст посилання",
|
||||
"Links with protocol \"%s\" are not supported": "Посилання з протоколом “%s” не підтримуються",
|
||||
"List item": "Елемент списку",
|
||||
"Lists": "Списки",
|
||||
"Loaded": "Завантажено",
|
||||
"Loading...": "Завантаження…",
|
||||
"Location": "Розташування",
|
||||
"Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at \"%s\" and resume the operation.": "Файл блокування вже утримується. Якщо ви знаєте, що синхронізація не відбувається, ви можете видалити файл блокування “%s” і продовжити роботу.",
|
||||
"Log": "Логи",
|
||||
"Login": "Увійти",
|
||||
"Login below.": "Увійдіть нижче.",
|
||||
"Login with Dropbox": "Ввійти з Dropbox",
|
||||
"Login with OneDrive": "Ввійти з OneDrive",
|
||||
"Logout": "Вийти",
|
||||
"Logs": "Журнали",
|
||||
"Make a donation": "Зробити пожертву",
|
||||
"Manage master password": "Керувати головним паролем",
|
||||
"Manage master password...": "Керувати головним паролем...",
|
||||
"Manage multiple users": "Керувати кількома користувачами",
|
||||
"Manage profiles": "Керувати профілями",
|
||||
"Manage your plugins": "Керування розширеннями",
|
||||
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, `status`, `decrypt-file`, and `target-status`.": "Керує конфігурацією E2EE. Команди: `enable`,` disable`, `decrypt`,` status`, `decrypt-file` та` target-status`.",
|
||||
"Manual": "Вручну",
|
||||
"Markdown": "Markdown",
|
||||
"Markdown + Front Matter": "Markdown + Front Matter",
|
||||
"Marks a to-do as done.": "Позначити завдання як виконане.",
|
||||
"Marks a to-do as non-completed.": "Позначає завдання як невиконане.",
|
||||
"Markup": "Markup",
|
||||
"Master Key %s": "Мастер ключ %s",
|
||||
"Master password": "Головний пароль",
|
||||
"Master password:": "Головний пароль:",
|
||||
"Max concurrent connections": "Максимальна кількість одночасних з’єднань",
|
||||
"Max Item Size": "Максимальний розмір елементу",
|
||||
"Max note or attachment size": "Максимальний розмір нотатки або вкладення",
|
||||
"Max Total Size": "Максимальний загальний розмір",
|
||||
"Missing keys": "Відсутні ключі",
|
||||
"Missing Master Keys": "Не знайдено мастер ключ",
|
||||
"Missing required argument: %s": "Відсутній обов’язковий аргумент: %s",
|
||||
"Missing required flag value: %s": "Відсутнє необхідне значення прапорця: %s",
|
||||
"Mobile data - auto-sync disabled": "Мобільні дані – автоматичну синхронізацію вимкнено",
|
||||
"More info": "Більше інформації",
|
||||
"More information": "Більше інформації",
|
||||
"More than one item match \"%s\". Please narrow down your query.": "Більше одного елемента відповідає “%s”. Будь ласка, звузьте свій запит.",
|
||||
"Move %d notes to notebook \"%s\"?": "Перемістити %d нотатку(-ок) до блокноту \"%s\"?",
|
||||
"Move to notebook": "Перемістити в блокнот",
|
||||
"Move to notebook...": "Перемістити в блокнот...",
|
||||
"Move to notebook:": "Перемістити в блокнот:",
|
||||
"Moves the given <item> to [notebook]": "Переміщує вказаний <item> до [notebook]",
|
||||
"n": "ні",
|
||||
"N": "Ні",
|
||||
"New note": "Нова нотатка",
|
||||
@@ -407,6 +562,7 @@
|
||||
"New tags:": "Нові теги:",
|
||||
"New to-do": "Нове завдання",
|
||||
"New version: %s": "Нова версія: %s",
|
||||
"Next match": "Наступне співпадіння",
|
||||
"Nextcloud": "Nextcloud",
|
||||
"Nextcloud password": "Nextcloud пароль",
|
||||
"Nextcloud username": "Nextcloud користувач",
|
||||
@@ -426,6 +582,8 @@
|
||||
"Nord": "Nord",
|
||||
"Not authentified with %s. Please provide any missing credentials.": "Не аутентифіковано за допомогою %s. Надайте будь-які відсутні облікові дані.",
|
||||
"Not downloaded": "Не завантажено",
|
||||
"Not generated": "Не згенеровано",
|
||||
"Not now": "Не зараз",
|
||||
"note": "нотатка",
|
||||
"Note": "Нотатка",
|
||||
"Note area growth factor": "Фатор зростання зони нотаток",
|
||||
@@ -433,6 +591,7 @@
|
||||
"Note attachments...": "Вкладення нотаток…",
|
||||
"Note body": "Тіло нотатки",
|
||||
"Note does not exist: \"%s\". Create it?": "Нотатка не існує: “%s”. Створити?",
|
||||
"Note editor": "Редактор нотатки",
|
||||
"Note has been saved.": "Примітку збережено.",
|
||||
"Note History": "Історія нотатки",
|
||||
"Note is not a to-do: \"%s\"": "Нотатка не є завданням: “%s”",
|
||||
@@ -440,12 +599,15 @@
|
||||
"Note list growth factor": "Фатор зростання списку нотаток",
|
||||
"Note properties": "Властивості нотатки",
|
||||
"Note title": "Заголовок нотатки",
|
||||
"Note&book": "Блокнот",
|
||||
"Note: Does not work in all desktop environments.": "Примітка: Не працює у всіх робочих середовищах.",
|
||||
"Note: When a note is shared, it will no longer be encrypted on the server.": "Примітка. Коли нотатка надається спільно, вона більше не буде зашифрована на сервері.",
|
||||
"Notebook": "Блокнот",
|
||||
"Notebook list growth factor": "Фактор зростання списку блокнотів",
|
||||
"Notebook: %s": "Блокнот: %s",
|
||||
"Notebooks": "Блокноти",
|
||||
"Notebooks cannot be named \"%s\", which is a reserved title.": "Блокноти не можна назвати “%s”, що є зарезервованою назвою.",
|
||||
"Notes": "Нотатки",
|
||||
"Notes and settings are stored in: %s": "Нотатки та налаштування зберігаються у: %s",
|
||||
"Notes can only be created within a notebook.": "Нотатки можна створювати лише в блокноті.",
|
||||
"Numbered List": "Нумерований список",
|
||||
@@ -460,10 +622,15 @@
|
||||
"Only one note can be printed at a time.": "Лише однв нотатка може бути роздрукована за раз.",
|
||||
"Open": "Відкрити",
|
||||
"Open %s": "Відкрити %s",
|
||||
"Open PDF viewer": "Відкрити переглядач PDF",
|
||||
"Open profile directory": "Відкрити каталог профілю",
|
||||
"Open Sync Wizard...": "Відкрити майстер синхронізації...",
|
||||
"Open...": "Відкрити...",
|
||||
"Operation cancelled": "Операцію скасовано",
|
||||
"Options": "Властивості",
|
||||
"Or create an account.": "Або створіть обліковий запис.",
|
||||
"Ordered list": "Упорядкований список",
|
||||
"Other applications...": "Інші програми...",
|
||||
"Output format: %s": "Вихідний формат: %s",
|
||||
"Page orientation for PDF export": "Орієнтація сторінки для експорту PDF",
|
||||
"Page size for PDF export": "Розмір сторінки для експорту в PDF",
|
||||
@@ -472,13 +639,18 @@
|
||||
"Password:": "Пароль:",
|
||||
"Passwords do not match!": "Паролі не співпадають!",
|
||||
"Paste": "Вставити",
|
||||
"Paste as text": "Вставити як текст",
|
||||
"Path:": "Шлях:",
|
||||
"PDF File": "PDF файл",
|
||||
"Per user. Minimum of %d users.": "На користувача. Мінімум %d користувачів.",
|
||||
"Permission needed": "Потрібен дозвіл",
|
||||
"Permission to use camera": "Дозвіл на використання камери",
|
||||
"Please click on \"%s\" to proceed, or set the passwords in the \"%s\" list below.": "Натисніть \"%s\", щоб продовжити, або встановіть паролі в списку \"%s\" нижче.",
|
||||
"Please confirm that you would like to re-encrypt your complete database.": "Підтвердьте, що хочете повторно зашифрувати повну базу даних.",
|
||||
"Please enter your password in the master key list below before upgrading the key.": "Будь ласка, введіть свій пароль у списку мастер ключів нижче перед оновленням ключа.",
|
||||
"Please note that if it is a large notebook, it may take a few minutes for all the notes to show up on the recipient's device.": "Зверніть увагу: якщо це великий блокнот, може знадобитися кілька хвилин, щоб усі нотатки відобразилися на пристрої одержувача.",
|
||||
"Please open the following URL in your browser to authenticate the application. The application will create a directory in \"Apps/Joplin\" and will only read and write files in this directory. It will have no access to any files outside this directory nor to any other personal data. No data will be shared with any third party.": "Будь ласка, відкрийте наступну URL-адресу у своєму браузері, щоб автентифікувати програму. Додаток створить каталог у “Apps/Joplin” і буде лише читати та записувати файли в цьому каталозі. Він не матиме доступу до будь-яких файлів поза цим каталогом, а також до будь-яких інших особистих даних. Ніякі дані не передаватимуться третім особам.",
|
||||
"Please record your voice...": "Будь ласка, запишіть свій голос...",
|
||||
"Please select a notebook first.": "Спочатку виберіть блокнот.",
|
||||
"Please select the note or notebook to be deleted first.": "Будь ласка, виберіть примітку або блокнот, який потрібно спершу видалити.",
|
||||
"Please select where the sync status should be exported to": "Виберіть, куди слід експортувати статус синхронізації",
|
||||
@@ -499,18 +671,43 @@
|
||||
"Press Ctrl+D or type \"exit\" to exit the application": "Натисніть Ctrl + D або введіть “exit”, щоб вийти з програми",
|
||||
"Press the shortcut": "Натисніть комбінацію клавіш",
|
||||
"Press the shortcut and then press ENTER. Or, press BACKSPACE to clear the shortcut.": "Натисніть комбінацію клавіш і потім ENTER. Або натисніть BACKSPACE щоб очистити комбінацію.",
|
||||
"Press to set the decryption password.": "Натисніть, щоб встановити пароль розшифровки.",
|
||||
"Previous match": "Попереднє співпадіння",
|
||||
"Previous versions of this note": "Попередні версії даної нотатки",
|
||||
"Print": "Друкувати",
|
||||
"Priority support": "Пріоритетна підтримка",
|
||||
"Privacy Policy": "Політика конфіденційності",
|
||||
"Pro": "Про",
|
||||
"Process failed payment subscriptions": "Обробка невдалих платежів за підписками",
|
||||
"Process oversized accounts": "Обробка великих облікових записів",
|
||||
"Process user deletions": "Процес видалення користувачів",
|
||||
"Profile": "Профіль",
|
||||
"Profile name": "Імя профілю",
|
||||
"Profile name:": "Імя профілю:",
|
||||
"Profile Version: %s": "Версія профайлу: %s",
|
||||
"Profiles": "Профілі",
|
||||
"Properties": "Властивості",
|
||||
"Proxy enabled": "Проксі ввімкнено",
|
||||
"Proxy timeout (seconds)": "Час очікування проксі (в секундах)",
|
||||
"Proxy URL": "URL проксі",
|
||||
"Public-private key pair:": "Пара відкритий-приватний ключ:",
|
||||
"Publish note...": "Опублікувати нотатку...",
|
||||
"Publish Notes": "Опублікувати примітки",
|
||||
"Publish notes to the internet": "Публікуйте нотатки в Інтернеті",
|
||||
"Quit": "Вихід",
|
||||
"Re-encrypt data": "Перезашифрувати дані",
|
||||
"Re-encryption": "Перешифрування",
|
||||
"Re-upload local data to sync target": "Повторно завантажте локальні дані для синхронізації",
|
||||
"Read more about it": "Дізнайтеся більше про це",
|
||||
"Read time: %s min": "Час читання: %s хв",
|
||||
"Recipient has accepted the invitation": "Одержувач прийняв запрошення",
|
||||
"Recipient has not yet accepted the invitation": "Одержувач ще не прийняв запрошення",
|
||||
"Recipient has rejected the invitation": "Одержувач відхилив запрошення",
|
||||
"Recipients:": "Одержувачі:",
|
||||
"Redo": "Відмінити",
|
||||
"Refresh": "Оновити",
|
||||
"Regular expression": "Регулярний вираз",
|
||||
"Reject": "Відхилити",
|
||||
"Remove": "Видалити",
|
||||
"Remove tag \"%s\" from all notes?": "Видалити тег “%s” з усіх нотаток?",
|
||||
"Remove this search from the sidebar?": "Видалити цей пошук із бічної панелі?",
|
||||
@@ -518,6 +715,13 @@
|
||||
"Rename notebook:": "Переіменувати блокнот:",
|
||||
"Rename tag:": "Переіменувати тег:",
|
||||
"Renames the given <item> (note or notebook) to <name>.": "Перейменовує даний <item> (нотатку або блокнот) на <name>.",
|
||||
"Renew token": "Оновити токен",
|
||||
"Replace": "Замінити",
|
||||
"Replace all": "Замінити все",
|
||||
"Replace with...": "Replace використовуючи...",
|
||||
"Replace: ": "Замінити: ",
|
||||
"Reset application layout": "Скинути макет програми",
|
||||
"Reset master password": "Скинути головний пароль",
|
||||
"Resources: %d.": "Ресурси: %d.",
|
||||
"Restart and upgrade": "Перезапустити і оновити",
|
||||
"Restart now": "Перезапустити зараз",
|
||||
@@ -529,46 +733,76 @@
|
||||
"Reverse sort order": "Зворотній порядок сортування",
|
||||
"Reverses the sorting order.": "Зворотній порядок сортування.",
|
||||
"Revision: %s (%s)": "Ревізія: %s (%s)",
|
||||
"Runs the commands contained in the text file. There should be one command per line.": "Виконує команди, що містяться в текстовому файлі. У кожному рядку має бути одна команда.",
|
||||
"S3": "S3",
|
||||
"S3 access key": "S3 access key",
|
||||
"S3 bucket": "S3 bucket",
|
||||
"S3 region": "S3 регіон",
|
||||
"S3 secret key": "S3 secret key",
|
||||
"S3 URL": "S3 посилання",
|
||||
"Safe mode is currently active. Note rendering and all plugins are temporarily disabled.": "Зараз активний безпечний режим. Відтворення приміток і всі плагіни тимчасово вимкнено.",
|
||||
"Save": "Зберегти",
|
||||
"Save alarm": "Зберегти будильник",
|
||||
"Save as %s": "Зберегти як %s",
|
||||
"Save as...": "Зберегти як...",
|
||||
"Save changes": "Зберегти зміни",
|
||||
"Save geo-location with notes": "Збережіть геолокацію з нотатками",
|
||||
"Search": "Пошук",
|
||||
"Search for plugins...": "Пошук рощширень…",
|
||||
"Search for...": "Шукати...",
|
||||
"Search in all the notes": "Пошук по всіх нотатках",
|
||||
"Search in current note": "Пошук в поточній нотатці",
|
||||
"Search...": "Пошук…",
|
||||
"Search:": "Пошук:",
|
||||
"Searches for the given <pattern> in all the notes.": "Шукає заданий <pattern> у всіх примітках.",
|
||||
"See the pre-release page for more details: %s": "Докладніше про тестову версію: %s",
|
||||
"Select": "Виберіть",
|
||||
"Select all": "Вибрати все",
|
||||
"Select emoji...": "Виберіть емодзі...",
|
||||
"Select file...": "Виберіть файл...",
|
||||
"Select parent notebook": "Виберіть батьківський блокнот",
|
||||
"Server is already running on port %d": "Сервер вже працює на порту %d",
|
||||
"Server is not running.": "Сервер не працює.",
|
||||
"Server is running on port %d": "Сервер працює на порту %d",
|
||||
"Set alarm": "Налаштувати будильник",
|
||||
"Set alarm:": "Налаштувати будильник:",
|
||||
"Set it to 0 to make it take the complete available space. Recommended width is 600.": "Встановіть значення 0, щоб він займав весь доступний простір. Рекомендована ширина 600.",
|
||||
"Set the password": "Встановити пароль",
|
||||
"Sets the property <name> of the given <note> to the given [value]. Possible properties are:\n\n%s": "Встановлює властивість <name> даного <note> до заданого [значення]. Можливі властивості:\n\n%s",
|
||||
"Share": "Поділитися",
|
||||
"Share and collaborate on a notebook": "Спільний доступ до блокнота та спільна робота з ним",
|
||||
"Share Notebook": "Поділитися блокнотом",
|
||||
"Share notebook...": "Поділитися блокнотом...",
|
||||
"Sharing access control": "Спільне керування доступом",
|
||||
"Sharing notebook...": "Спільний доступ до блокнота...",
|
||||
"Shortcuts are not available in CLI mode.": "Скорочення клавіатури недоступні в режимі CLI.",
|
||||
"Show advanced": "Показати розширені",
|
||||
"Show Advanced Settings": "Показати розширені налаштування",
|
||||
"Show all": "Показати все",
|
||||
"Show completed to-dos": "Показувати завершені списки справ",
|
||||
"Show disabled": "Показати вимкнені",
|
||||
"Show disabled keys": "Показати вимкнені клавіші",
|
||||
"Show more actions": "Показати більше дій",
|
||||
"Show note counts": "Показати лічильники нотатки",
|
||||
"Show sort order buttons": "Показати кнопки порядку сортування",
|
||||
"Show tray icon": "Показувати значок в меню",
|
||||
"Show/hide the sidebar": "Показати/приховати бічну панель",
|
||||
"Sidebar": "Бічна панель",
|
||||
"Size": "Розмір",
|
||||
"Skip this version": "Пропустити цю версію",
|
||||
"Skipped items: %d (use --retry-failed-items to retry decrypting them)": "Пропущені елементи: %d (використовуйте —retry-failed-items, щоб спробувати їх дешифрувати)",
|
||||
"Skipped: %d.": "Пропущено: %d.",
|
||||
"Solarised Dark": "Solarised Dark",
|
||||
"Solarised Light": "Solarised Light",
|
||||
"Some items cannot be decrypted.": "Деякі елементи не можуть бути дешифровані.",
|
||||
"Some items cannot be synchronised.": "Деякі елементи не можуть бути синхронізовані.",
|
||||
"Some items cannot be synchronised. Press for more info.": "Деякі елементи не можуть бути синхронізовані. Натисніть для отримання додаткової інформації.",
|
||||
"Sort notebooks by": "Сортувати блокноти за",
|
||||
"Sort notes by": "Сортувати нотатки по",
|
||||
"Sort selected lines": "Відсортувати вибрані рядки",
|
||||
"Sorts the item by <field> (eg. title, updated_time, created_time).": "Сортувати елементи за <field> (заголовок, час оновлення, час створення, тощо).",
|
||||
"Source format: %s": "Формат джерела: %s",
|
||||
"Source: ": "Джерело: ",
|
||||
"Specify the port that should be used by the API server. If not set, a default will be used.": "Вкажіть порт, який повинен використовувати сервер API. Якщо не встановлено, використовуватиметься за замовчуванням.",
|
||||
"Spell checker": "Перевірка правопису",
|
||||
"Split View": "Розділений показ",
|
||||
@@ -588,21 +822,29 @@
|
||||
"Step 2: Install the extension": "Крок 2: Встановіть розширення",
|
||||
"Stop": "Зупинити",
|
||||
"Stop external editing": "Зупинити зовнішнє редагування",
|
||||
"Storage space": "Місце для зберігання",
|
||||
"Strikethrough": "Перекреслення",
|
||||
"strong text": "жирний текст",
|
||||
"Submit": "Підтвердити",
|
||||
"Subscript": "Підрядковий",
|
||||
"Success! Synchronisation configuration appears to be correct.": "Успіх! Конфігурація синхронізації видається правильною.",
|
||||
"Superscript": "Надрядковий",
|
||||
"Swap line down": "Замінити місцями до низу",
|
||||
"Swap line up": "Замінити місцями вгору",
|
||||
"Switch between note and to-do type": "Переключення між нотаткою і списком справ",
|
||||
"Switch profile": "Змінити профіль",
|
||||
"Switch to note type": "Переключити до нотатки",
|
||||
"Switch to profile %d": "Перейти до профілю %d",
|
||||
"Switch to to-do type": "Переключити до списку справ",
|
||||
"Switches to [notebook] - all further operations will happen within this notebook.": "Перемикається на [блокнот] - усі подальші операції відбуватимуться в цьому блокноті.",
|
||||
"Sync as many devices as you want": "Синхронізуйте скільки завгодно пристроїв",
|
||||
"Sync Status": "Статус синхронізації",
|
||||
"Sync status (synced items / total items)": "Статус синзронізації (синзронізовані елементи / всього елементів)",
|
||||
"Sync target must be upgraded! Run `%s` to proceed.": "Потрібно оновити ціль синхронізації! Запустіть `%s`, щоб продовжити.",
|
||||
"Sync Target Upgrade": "Оновлення цілі синхронизації",
|
||||
"Sync to provided target (defaults to sync.target config value)": "Синхронізуватись із вказаною ціллю (за замовчуванням значення конфігурації sync.target)",
|
||||
"Sync Version: %s": "Версія синхронізації: %s",
|
||||
"Sync your notes": "Сортувати нотатки за",
|
||||
"Synchronisation": "Синхронізація",
|
||||
"Synchronisation interval": "Інтервал синхронізації",
|
||||
"Synchronisation is already in progress.": "Синхронізація вже триває.",
|
||||
@@ -610,14 +852,23 @@
|
||||
"Synchronisation target": "Ціль синхронізації",
|
||||
"Synchronisation target: %s (%s)": "Ціль синхронізації: %s (%s)",
|
||||
"Synchronise": "Синхронізувати",
|
||||
"Synchronise only over WiFi connection": "Синхронізувати лише через Wi-Fi",
|
||||
"Synchronises with remote storage.": "Синхронізується з віддаленим сховищем.",
|
||||
"Synchronising...": "Синхронізація…",
|
||||
"Synchronizing...": "Синхронізую…",
|
||||
"Tabloid": "Tabloid",
|
||||
"tag1, tag2, ...": "тег1, тег2, ...",
|
||||
"Tagged: %d.": "З тегами: %d.",
|
||||
"Tags": "Теги",
|
||||
"Take photo": "Зробити фото",
|
||||
"Task list": "Список завдань",
|
||||
"Tasks": "Завдання",
|
||||
"Teams": "Команди",
|
||||
"Text editor command": "Команда текстового редактора",
|
||||
"Thank you! Your Joplin Cloud account is now setup and ready to use.": "Дякую тобі! Ваш обліковий запис Joplin Cloud налаштовано та готовий до використання.",
|
||||
"The active profile cannot be deleted. Switch to a different profile and try again.": "Активний профіль не можна видалити. Перейдіть на інший профіль та повторіть спробу.",
|
||||
"The app is now going to close. Please relaunch it to complete the process.": "Додаток зараз буде закрито. Будь ласка, перезапустіть його, щоб завершити процес.",
|
||||
"The application did not close properly. Would you like to start in safe mode?": "Програма не закрилася належним чином. Бажаєте почати в безпечному режимі?",
|
||||
"The application has been authorised - you may now close this browser tab.": "Додаток авторизовано - тепер ви можете закрити цю вкладку браузера.",
|
||||
"The application has been authorised!": "Додаток авторизовано!",
|
||||
"The application has been successfully authorised.": "Додаток успішно авторизовано.",
|
||||
@@ -627,27 +878,37 @@
|
||||
"The default admin password is insecure and has not been changed! [Change it now](%s)": "Пароль адміністратора за замовчуванням небезпечний і його не змінювали! [Змінити зараз](%s)",
|
||||
"The default encryption method has been changed to a more secure one and it is recommended that you apply it to your data.": "Метод шифрування за замовчуванням змінено на більш безпечний, і рекомендується застосовувати його до своїх даних.",
|
||||
"The default encryption method has been changed, you should re-encrypt your data.": "Метод шифрування за замовчуванням змінено, вам слід повторно зашифрувати дані.",
|
||||
"The default profile cannot be deleted": "Стандартний профіль не моливо видалити",
|
||||
"The editor command (may include arguments) that will be used to open a note. If none is provided it will try to auto-detect the default editor.": "Команда редактора (може містити аргументи), яка буде використана для відкриття нотатки. Якщо нічого не вказано, він спробує автоматично визначити редактор за замовчуванням.",
|
||||
"The factor property sets how the item will grow or shrink to fit the available space in its container with respect to the other items. Thus an item with a factor of 2 will take twice as much space as an item with a factor of 1.Restart app to see changes.": "Властивість фактору встановлює, як елемент буде рости або зменшуватися, щоб розмістити вільний простір у своєму контейнері щодо інших предметів. Таким чином, предмет із коефіцієнтом 2 займе вдвічі більше місця, ніж предмет із коефіцієнтом 1. Перезапустіть програму, щоб побачити зміни.",
|
||||
"The following attachments are being watched for changes:": "Наступні вкладення переглядаються для змін:",
|
||||
"The following keys use an out-dated encryption algorithm and it is recommended to upgrade them. The upgraded key will still be able to decrypt and encrypt your data as usual.": "У наступних ключах використовується застарілий алгоритм шифрування, тому їх рекомендується оновити. Оновлений ключ як і раніше зможе розшифровувати та шифрувати ваші дані.",
|
||||
"The Joplin mobile app does not currently support this type of link: %s": "Мобільний додаток Joplin наразі не підтримує такий тип посилань: %s",
|
||||
"The Joplin team has vetted this plugin and it meets our standards for security and performance.": "Команда Joplin перевірила цей плагін, і він відповідає нашим стандартам безпеки та продуктивності.",
|
||||
"The keys with these IDs are used to encrypt some of your items, however the application does not currently have access to them. It is likely they will eventually be downloaded via synchronisation.": "Ключі з цими ідентифікаторами використовуються для шифрування деяких ваших елементів, однак програма наразі не має до них доступу. Цілком ймовірно, що з часом їх буде завантажено через синхронізацію.",
|
||||
"The master key has been upgraded successfully!": "Головний ключ успішно оновлений!",
|
||||
"The master keys with these IDs are used to encrypt some of your items, however the application does not currently have access to them. It is likely they will eventually be downloaded via synchronisation.": "Мастер ключ з цими ідентифікаторами використовуються для шифрування деяких ваших елементів, однак програма наразі не має до них доступу. Цілком ймовірно, що вони з часом будуть завантажені за допомогою синхронізації.",
|
||||
"The note \"%s\" has been successfully restored to the notebook \"%s\".": "Примітку “%s” успішно відновлено до блокнота “%s”.",
|
||||
"The notebook could not be saved: %s": "Блокнот не може бути збережено: %s",
|
||||
"The notes have been imported: %s": "Імпортовано нотаток: %s",
|
||||
"The possible commands are:": "Можливі команди:",
|
||||
"The recipient could not be removed from the list. Please try again.\n\nThe error was: \"%s\"": "Не вдалося видалити одержувача зі списку. Будь ласка спробуйте ще раз.\n\nВиникла наступна помилка: \"%s\"",
|
||||
"The sync target needs to be upgraded before Joplin can sync. The operation may take a few minutes to complete and the app needs to be restarted. To proceed please click on the link.": "Цілі синхронізації потрібно оновити, перш ніж Joplin зможе синхронізувати. Завершення операції може зайняти кілька хвилин і програму потрібно перезапустити. Щоб продовжити, натисніть на посилання.",
|
||||
"The sync target needs to be upgraded. Press this banner to proceed.": "Ціль синхронізації потрібно оновити. Натисніть цей банер, щоб продовжити.",
|
||||
"The tag \"%s\" already exists. Please choose a different name.": "Тег “%s” уже існує. Будь ласка, виберіть інше ім’я.",
|
||||
"The target to synchronise to. Each sync target may have additional parameters which are named as `sync.NUM.NAME` (all documented below).": "Ціль синхронізації. Кожна ціль може мати додаткові параметри іменовані `sync.NUM.NAME` (задокументовані нижче).",
|
||||
"The Web Clipper needs your authorisation to access your data.": "Web Clipper потребує Вашої авторизації для доступу до Ваших даних.",
|
||||
"The web clipper service is enabled and set to auto-start.": "Сервіс web clipper увімкнено та встановлено на автоматичний запуск.",
|
||||
"The web clipper service is not enabled.": "Сервіс web clipper не ввімкнено.",
|
||||
"The WebDAV implementation of %s is incompatible with Joplin, and as such is no longer supported. Please use a different sync method.": "Реалізація WebDAV %s несумісна з Joplin, тому більше не підтримується. Будь ласка, скористайтеся іншим методом синхронізації.",
|
||||
"Theme": "Тема",
|
||||
"There are currently no notes. Create one by clicking on the (+) button.": "На даний момент немає нотаток. Створіть, натиснувши кнопку (+).",
|
||||
"There are unsaved changes.": "Є незбережені зміни.",
|
||||
"There is currently no notebook. Create one by clicking on \"New notebook\".": "В даний час немає блокнота. Створіть його, натиснувши “Новий блокнот”.",
|
||||
"There is no data to export.": "Немає даних для експорту.",
|
||||
"There was a [conflict](%s) on the attachment below.\n\n%s": "[конфлікт](%s) oу вкладеннях нижче.\n\n%s",
|
||||
"There was an error downloading this attachment:": "Під час завантаження цього вкладення сталася помилка:",
|
||||
"There was an error setting up your Joplin Cloud account. Please verify your email and password and try again. Error was:\n\n%s": "Під час налаштування облікового запису Joplin Cloud сталася помилка. Перевірте свою електронну адресу та пароль і повторіть спробу. Деталі помилки:\n\n%s",
|
||||
"These items will remain on the device but will not be uploaded to the sync target. In order to find these items, either search for the title or the ID (which is displayed in brackets above).": "Ці елементи залишаться на пристрої, але не будуть завантажені до цілі синхронізації. Для того, щоб знайти ці елементи, знайдіть заголовок або ідентифікатор (який відображається в дужках вище).",
|
||||
"These plugins enhance the Markdown renderer with additional features. Please note that, while these features might be useful, they are not standard Markdown and thus most of them will only work in Joplin. Additionally, some of them are *incompatible* with the WYSIWYG editor. If you open a note that uses one of these plugins in that editor, you will lose the plugin formatting. It is indicated below which plugins are compatible or not with the WYSIWYG editor.": "Ці плагіни покращують візуалізатор Markdown додатковими функціями. Зверніть увагу, що, хоча ці функції можуть бути корисними, вони не є стандартними Markdown, тому більшість із них працюватимуть лише в Joplin. Крім того, деякі з них *несумісні* з редактором WYSIWYG. Якщо ви відкриєте нотатку, яка використовує один із цих плагінів у цьому редакторі, ви втратите форматування плагіна. Внизу вказано, які плагіни сумісні чи ні з редактором WYSIWYG.",
|
||||
"This attachment is not downloaded or not decrypted yet": "Це вкладення ще не завантажено або ще не розшифроване",
|
||||
@@ -662,10 +923,12 @@
|
||||
"This service allows the browser extension to communicate with Joplin. When enabling it your firewall may ask you to give permission to Joplin to listen to a particular port.": "Ця послуга дозволяє розширенню браузера спілкуватися з Joplin. Увімкнувши його, ваш брандмауер може попросити вас надати дозвіл Joplin прослуховувати певний порт.",
|
||||
"This will allow Joplin to run in the background. It is recommended to enable this setting so that your notes are constantly being synchronised, thus reducing the number of conflicts.": "Це дозволить Joplin працювати у фоновому режимі. Рекомендується ввімкнути цей параметр, щоб ваші нотатки постійно синхронізувались, таким чином зменшуючи кількість конфліктів.",
|
||||
"This will open a new screen. Save your current changes?": "Це відкриє новий екран. Зберегти поточні зміни?",
|
||||
"This will remove the notebook from your collection and you will no longer have access to its content. Do you wish to continue?": "Блокнот буде видалено з вашої колекції, і Ви більше не матимете доступу до його вмісту. Ви бажаєте продовжити?",
|
||||
"Time format": "Формат часу",
|
||||
"title": "заголовок",
|
||||
"Title": "Заголовок",
|
||||
"To allow Joplin to synchronise with Dropbox, please follow the steps below:": "Щоб дозволити Joplin синхронізуватися з Dropbox, виконайте наведені нижче дії:",
|
||||
"To continue, please enter your master password below.": "Щоб продовжити, введіть свій головний пароль нижче.",
|
||||
"To delete a tag, untag the associated notes.": "Щоб видалити тег, зніміть позначки з відповідних нотаток.",
|
||||
"To delete: %d": "До видалення: %d",
|
||||
"To enter command line mode, press \":\"": "Щоб увійти в режим командного рядка, натисніть “:”",
|
||||
@@ -674,18 +937,26 @@
|
||||
"To maximise/minimise the console, press \"tc\".": "Щоб розгорнути / згорнути консоль, натисніть “tc”.",
|
||||
"To move from one pane to another, press Tab or Shift+Tab.": "Щоб перейти з однієї панелі на іншу, натисніть Tab або Shift+Tab.",
|
||||
"To retry decryption of these items. Run `e2ee decrypt --retry-failed-items`": "Повторити спробу дешифрування цих елементів. Запустіть `e2ee decrypt —retry-failed-items`",
|
||||
"To switch the profile, the app is going to close and you will need to restart it.": "Щоб змінити профіль, програма закриється, і вам потрібно буде її перезапустити.",
|
||||
"To work correctly, the app needs the following permissions. Please enable them in your phone settings, in Apps > Joplin > Permissions": "Для коректної роботи додатку потрібні такі дозволи. Будь-ласка, увімкніть їх у налаштуваннях телефону, у Додатки> Joplin> Дозволи",
|
||||
"to-do": "справи",
|
||||
"to-do": "завдання",
|
||||
"to-do: %s": "завдання: %s",
|
||||
"Toggle comment": "Переключити коментар",
|
||||
"Toggle development tools": "Перемикач інструментів розробника",
|
||||
"Toggle editor layout": "Переключити макет редактора",
|
||||
"Toggle editors": "Переключити редактори",
|
||||
"Toggle external editing": "Переключити зовнішнє редагування",
|
||||
"Toggle note list": "Переключити список нотаток",
|
||||
"Toggle own sort order": "Переключити власний порядок сортування",
|
||||
"Toggle safe mode": "Переключити безпечний режим",
|
||||
"Toggle sidebar": "Переключити бокову панель",
|
||||
"Toggle sort order field": "Переключити поле порядку сортування",
|
||||
"Token has been copied to the clipboard!": "Токен скопійовано в буфер обміну!",
|
||||
"Tools": "Інструменти",
|
||||
"Total Size": "Загальний розмір",
|
||||
"Total: %d/%d": "Всього: %d/%d",
|
||||
"Try again": "Спробувати знову",
|
||||
"Try it now": "Спробувати зараз",
|
||||
"Type `help [command]` for more information about a command; or type `help all` for the complete usage information.": "Введіть `help [command]` для отримання додаткової інформації про команду; або введіть `help all` для отримання повної інформації про використання.",
|
||||
"Type `joplin help` for usage information.": "Введіть `joplin help` для отримання інформації про використання.",
|
||||
"Type a note title or part of its content to jump to it. Or type # followed by a tag name, or @ followed by a notebook name. Or type : to search for commands.": "Введіть заголовок нотатки або частину її вмісту, щоб перейти до неї. Або введіть # а потім ім'я тега, або @, а потім ім'я блокнота. Або введіть : для пошуку команд.",
|
||||
@@ -695,14 +966,21 @@
|
||||
"Undo": "Сказувати",
|
||||
"Unknown flag: %s": "Невідомий прапорець: %s",
|
||||
"Unknown item type downloaded - please upgrade Joplin to the latest version": "Завантажено невідомий тип елементу - оновіть Joplin до останньої версії",
|
||||
"Unordered list": "Unordered list",
|
||||
"Unpublish note": "Скасувати публікацію примітки",
|
||||
"Unshare": "Скасувати спільний доступ",
|
||||
"Unshare this notebook? The recipients will no longer have access to its content.": "Скасувати доступ до цього блокнота? Одержувачі більше не матимуть доступу до його вмісту.",
|
||||
"Unsupported image type: %s": "Непідтримуваний тип зображення: %s",
|
||||
"Unsupported link or message: %s": "Непідтримуване посилання або повідомлення: %s",
|
||||
"Untitled": "Без назви",
|
||||
"Update": "Оновити",
|
||||
"Update profile": "Оновити профіль",
|
||||
"Update total sizes": "Оновити загальні розміри",
|
||||
"Updated": "Оновлено",
|
||||
"updated date": "оновлена дата",
|
||||
"Updated local items: %d.": "Оновлено локальних елементів: %d.",
|
||||
"Updated remote items: %d.": "Оновлено віддалених елементів: %d.",
|
||||
"Updated: ": "Оновлено: ",
|
||||
"Updated: %d.": "Оновлено: %d.",
|
||||
"Updated: %s": "Оновлено: %s",
|
||||
"Updating...": "Оновлення…",
|
||||
@@ -710,16 +988,26 @@
|
||||
"Upgrade the sync target to the latest version.": "Оновіть ціль синхронізації до останньої версії.",
|
||||
"URL": "Посилання",
|
||||
"Usage: %s": "Використання: %s",
|
||||
"Use biometrics to secure access to the app": "Використовуйте біометричні дані для безпечного доступу до програми",
|
||||
"Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE": "Використовуйте формат довгого списку. Формат - ID, NOTE_COUNT (для блокнота), DATE, TODO_CHECKED (для завдань), TITLE",
|
||||
"Use spell checker": "Використовуйте перевірку правопису",
|
||||
"Use the arrows and page up/down to scroll the lists and text areas (including this console).": "За допомогою стрілок та page up/down прокручуйте списки та текстові області (включаючи цю консоль).",
|
||||
"Use the arrows to move the layout items. Press \"Escape\" to exit.": "Використовуйте стрілки для переміщення елементів макета. Натисніть “Escape”, щоб вийти.",
|
||||
"Use this to rebuild the search index if there is a problem with search. It may take a long time depending on the number of notes.": "Використовуйте це, щоб відновити індекс пошуку, якщо проблема з пошуком. Це може зайняти багато часу, залежно від кількості нотаток.",
|
||||
"Use your biometrics to secure access to your application. You can always set it up later in Settings.": "Використовуйте свої біометричні дані, щоб захистити доступ до своєї програми. Ви завжди можете налаштувати це пізніше в Налаштуваннях.",
|
||||
"Used for most text in the markdown editor. If not found, a generic proportional (variable width) font is used.": "Використовується для більшості текстів у редакторі розміток. Якщо не знайдено, використовується загальний пропорційний (змінної ширини) шрифт.",
|
||||
"Used where a fixed width font is needed to lay out text legibly (e.g. tables, checkboxes, code). If not found, a generic monospace (fixed width) font is used.": "Використовується там, де потрібен шрифт фіксованої ширини для розбірливого розміщення тексту (наприклад, таблиць, прапорців, коду). Якщо не знайдено, використовується загальний моноширинний (з фіксованою шириною) шрифт.",
|
||||
"User deletions": "Видалення користувача",
|
||||
"Users": "Користувачі",
|
||||
"Valid": "Дійсний",
|
||||
"Verify your identity": "Підтвердьте свою особу",
|
||||
"View": "Переглянути",
|
||||
"View on map": "Показати на карті",
|
||||
"View them now": "Показати елемент зараз",
|
||||
"Viewer": "Переглядач",
|
||||
"Vim": "Vim",
|
||||
"Voice typing language files (URL)": "Мовні файли голосового введення (URL)",
|
||||
"Voice typing...": "Голосовий набір...",
|
||||
"Warning": "Попередження",
|
||||
"Warning: not all resources shown for performance reasons (limit: %s).": "Попередження: не всі ресурси відображаються з міркувань продуктивності (ліміт: %s).",
|
||||
"Web Clipper": "Web Clipper",
|
||||
@@ -728,7 +1016,8 @@
|
||||
"WebDAV URL": "WebDAV посилання",
|
||||
"WebDAV username": "WebDAV користувач",
|
||||
"Website and documentation": "Вебсайт та документація",
|
||||
"Welcome to Joplin!\n\nType `:help shortcuts` for the list of keyboard shortcuts, or just `:help` for usage information.\n\nFor example, to create a notebook press `mb`; to create a note press `mn`.": "Ласкаво просимо до Ощздшт!\n\nВведіть `:help shortcuts` для списку комбінацій клавіш або просто `:help` для інформації про використання.\n\nНаприклад, для створення блокнота натисніть `mb`; щоб створити нотатку, натисніть “mn”.",
|
||||
"Welcome to Joplin!\n\nType `:help shortcuts` for the list of keyboard shortcuts, or just `:help` for usage information.\n\nFor example, to create a notebook press `mb`; to create a note press `mn`.": "Ласкаво просимо до Joplin!\n\nВведіть `:help shortcuts` для списку комбінацій клавіш або просто `:help` для інформації про використання.\n\nНаприклад, для створення блокнота натисніть `mb`; щоб створити нотатку, натисніть “mn”.",
|
||||
"Welcome!": "Ласкаво просимо!",
|
||||
"When creating a new note:": "Коли створюжться нова нотатка:",
|
||||
"When creating a new to-do:": "Коли створюжться новий список справ:",
|
||||
"Words": "Слова",
|
||||
@@ -743,6 +1032,8 @@
|
||||
"You may use the tool below to re-encrypt your data, for example if you know that some of your notes are encrypted with an obsolete encryption method.": "Ви можете скористатися наведеним нижче інструментом для повторного шифрування даних, наприклад, якщо ви знаєте, що деякі ваші нотатки зашифровані застарілим методом шифрування.",
|
||||
"Your choice: ": "Ваш вибір: ",
|
||||
"Your data is going to be re-encrypted and synced again.": "Ваші дані будуть повторно зашифровані та знову синхронізовані.",
|
||||
"Your password is needed to decrypt some of your data.": "Ваш пароль необхідний для розшифровки деяких Ваших даних.",
|
||||
"Your password is needed to decrypt some of your data. Type `:e2ee decrypt` to set it.": "Ваш пароль необхідний для розшифровки деяких Ваших даних. Наберіть `:e2ee decrypt` щоб його встановити.",
|
||||
"Your permission to use your camera is required.": "Ваш дозвіл на використання камери є обов’язковим.",
|
||||
"Your version: %s": "Ваша версія: %s",
|
||||
"Zoom In": "Збільшити",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"%d MB per note or attachment": "每个笔记或附件%dMB",
|
||||
"%d minutes": "%d 分钟",
|
||||
"%d notes match this pattern. Delete them?": "有 %d 条笔记匹配。是否删除?",
|
||||
"%s": "%s",
|
||||
"%s %s (%s, %s)": "%s %s (%s, %s)",
|
||||
"%s (%s) could not be uploaded: %s": "%s (%s) 无法上传:%s",
|
||||
"%s (%s) would like to share a notebook with you.": "%s (%s) 想要分享笔记本给您。",
|
||||
@@ -53,6 +54,7 @@
|
||||
"Active": "正在使用",
|
||||
"Actual Size": "实际大小",
|
||||
"Add body": "添加内容",
|
||||
"Add new": "新增",
|
||||
"Add or remove tags:": "添加或删除标签:",
|
||||
"Add recipient:": "添加收件人:",
|
||||
"Add title": "添加标题",
|
||||
@@ -74,6 +76,7 @@
|
||||
"Application": "应用程序",
|
||||
"Apply": "应用",
|
||||
"Are you sure you want to renew the authorisation token?": "确定要更新授权令牌吗?",
|
||||
"Are you sure you want to return to the default layout? The current layout configuration will be lost.": "确定要返回到默认布局吗?当前布局配置将丢失。",
|
||||
"Arguments:": "参数:",
|
||||
"Aritim Dark": "暗黑 (Aritim)",
|
||||
"Attach": "附加",
|
||||
@@ -96,10 +99,12 @@
|
||||
"Automatically switch theme to match system theme": "根据系统主题自动切换",
|
||||
"Back": "返回",
|
||||
"Basic": "基本",
|
||||
"Biometric unlock is not setup on the device. Please set it up in order to unlock Joplin. If the device is on lockout, consider switching it off and on to reset biometrics scanning.": "设备上未设置生物识别解锁。请设置它以解锁Joplin。如果设备处于锁定状态,请考虑将其关闭和打开以重置生物特征扫描。",
|
||||
"Bold": "加粗",
|
||||
"Browse all plugins": "浏览所有插件",
|
||||
"Browse...": "浏览...",
|
||||
"Bulleted List": "无序列表",
|
||||
"Can Share": "分享",
|
||||
"Cancel": "取消",
|
||||
"Cancelling background synchronisation... Please wait.": "正在取消后台同步... 请稍候。",
|
||||
"Cancelling...": "正在取消...",
|
||||
@@ -108,6 +113,7 @@
|
||||
"Cannot change encrypted item": "无法更改已加密条目",
|
||||
"Cannot copy note to \"%s\" notebook": "无法复制笔记到笔记本 “%s”",
|
||||
"Cannot find \"%s\".": "无法找到 “%s”。",
|
||||
"Cannot find: \"%s\"": "无法找到 “%s”",
|
||||
"Cannot initialise synchroniser.": "无法启动同步。",
|
||||
"Cannot load \"%s\" module for format \"%s\" and output \"%s\"": "无法为格式 “%2$s” 和输出 “%3$s” 加载 “%1$s” 模块",
|
||||
"Cannot load \"%s\" module for format \"%s\" and target \"%s\"": "无法加载为格式 “%2$s” 和目标 “%3$s” 加载 “%1$s” 模块",
|
||||
@@ -135,6 +141,7 @@
|
||||
"Click to add tags...": "单击以添加标签...",
|
||||
"Client ID: %s": "客户端 ID: %s",
|
||||
"Close": "关闭",
|
||||
"Close dropdown": "关闭下拉列表",
|
||||
"Close Window": "关闭窗口",
|
||||
"Code": "代码",
|
||||
"Code Block": "代码块",
|
||||
@@ -163,6 +170,7 @@
|
||||
"Continue": "继续",
|
||||
"Convert to note": "转换为笔记",
|
||||
"Convert to todo": "转换为待办事项",
|
||||
"Converting speech to text...": "正在将语音转换为文本...",
|
||||
"Copy": "复制",
|
||||
"Copy dev mode command to clipboard": "复制开发者模式命令到剪贴板",
|
||||
"Copy external link": "复制外部链接地址",
|
||||
@@ -181,16 +189,18 @@
|
||||
"Could not switch profile: %s": "无法切换到配置文件:%s",
|
||||
"Could not upgrade master key: %s": "无法升级主密钥(master key):%s",
|
||||
"Could not verify the share status of this notebook - aborting. Please try again when you are connected to the internet.": "无法验证此笔记的分享状态 — 正在终止。请在连接到互联网后再次尝试。",
|
||||
"Could not verify your identify: %s": "无法验证您的身份: %s",
|
||||
"Create": "创建",
|
||||
"Create a new notebook under a parent notebook.": "在父笔记本下创建新笔记本。",
|
||||
"Create a notebook": "新建一个笔记本",
|
||||
"Create new profile...": "创建新的配置文件...",
|
||||
"Create notebook": "新建笔记本",
|
||||
"Create user": "创建用户",
|
||||
"Created": "创建日期",
|
||||
"created date": "创建日期",
|
||||
"Created local items: %d.": "已新建本地项目:%d。",
|
||||
"Created locally": "已新建本地项目",
|
||||
"Created remote items: %d.": "已新建远程项目:%d。",
|
||||
"Created local items: %d.": "已新建本地条目:%d。",
|
||||
"Created locally": "已新建本地条目",
|
||||
"Created remote items: %d.": "已新建远程条目:%d。",
|
||||
"Created: ": "创建: ",
|
||||
"Created: %d.": "已创建:%d 条。",
|
||||
"Created: %s": "创建:%s",
|
||||
@@ -234,8 +244,8 @@
|
||||
"Delete these %d notes?": "是否删除这 %d 条笔记?",
|
||||
"Delete this invitation? The recipient will no longer have access to this shared notebook.": "是否删除该邀请?收件人将无法再次访问此共享笔记本。",
|
||||
"Delete this profile?": "是否删除此配置文件?",
|
||||
"Deleted local items: %d.": "已删除本地项目:%d。",
|
||||
"Deleted remote items: %d.": "已删除远程项目:%d。",
|
||||
"Deleted local items: %d.": "已删除本地条目:%d。",
|
||||
"Deleted remote items: %d.": "已删除远程条目:%d。",
|
||||
"Deletes the given notebook.": "删除选定的笔记本。",
|
||||
"Deletes the notebook without asking for confirmation.": "删除笔记本(不要求确认)。",
|
||||
"Deletes the notes matching <note-pattern>.": "删除符合 <note-pattern> 的笔记。",
|
||||
@@ -253,7 +263,7 @@
|
||||
"Dismiss": "忽略",
|
||||
"Displays a geolocation URL for the note.": "显示该笔记的地理位置 URL。",
|
||||
"Displays only the first top <num> notes.": "只显示最上方的 <num> 条笔记。",
|
||||
"Displays only the items of the specific type(s). Can be `n` for notes, `t` for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the to-dos, while `-tnt` would display notes and to-dos.": "仅显示指定类型的项目。可以把 `n` 用于笔记,`t` 用于待办事项,或者 `nt` 用于笔记和待办事项(示例:`-tt` 只会显示待办事项,当使用 `-tnt` 时将会显示笔记和待办事项。)",
|
||||
"Displays only the items of the specific type(s). Can be `n` for notes, `t` for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the to-dos, while `-tnt` would display notes and to-dos.": "仅显示指定类型的条目。可以把 `n` 用于笔记,`t` 用于待办事项,或者 `nt` 用于笔记和待办事项(示例:`-tt` 只会显示待办事项,当使用 `-tnt` 时将会显示笔记和待办事项。)",
|
||||
"Displays summary about the notes and notebooks.": "显示关于笔记与笔记本的概况。",
|
||||
"Displays the complete information about note.": "显示关于笔记的完整信息。",
|
||||
"Displays the given note.": "显示选定笔记。",
|
||||
@@ -270,6 +280,7 @@
|
||||
"Downloaded and decrypted": "已下载并解密",
|
||||
"Downloaded and encrypted": "已下载并加密",
|
||||
"Downloading": "下载中",
|
||||
"Downloading %s language files...": "下载%s语言文件中...",
|
||||
"Downloading resources...": "下载资源中...",
|
||||
"Dracula": "德古拉紫(Dracula)",
|
||||
"Drop notes or files here": "将笔记或文件拖到此处",
|
||||
@@ -304,6 +315,7 @@
|
||||
"Enable ^sup^ syntax": "启用 ^sup^ 语法",
|
||||
"Enable abbreviation syntax": "启用缩写语法",
|
||||
"Enable audio player": "启用音频播放器",
|
||||
"Enable biometrics authentication?": "启用生物特征验证?",
|
||||
"Enable deflist syntax": "启用 deflist 语法",
|
||||
"Enable encryption": "启用加密",
|
||||
"Enable footnotes": "启用脚注",
|
||||
@@ -316,7 +328,9 @@
|
||||
"Enable note history": "启用笔记历史",
|
||||
"Enable PDF viewer": "启用 PDF 查看器",
|
||||
"Enable soft breaks": "启用软换行",
|
||||
"Enable spellcheck in the text editor": "在文本编辑器中启用拼写检查",
|
||||
"Enable table of contents extension": "启用目录扩展 ([TOC])",
|
||||
"Enable the Markdown toolbar": "启用“标记”工具栏",
|
||||
"Enable typographer support": "启用 Typographer 支持",
|
||||
"Enable video player": "启用视频播放器",
|
||||
"Enable Web Clipper Service": "启用网页剪藏器",
|
||||
@@ -358,13 +372,13 @@
|
||||
"Fail-safe: Do not wipe out local data when sync target is empty (often the result of a misconfiguration or bug)": "故障保护(Fail-safe) :当同步目标为空时(通常是配置错误或Bug),不要删除本地数据",
|
||||
"Fatal error:": "严重错误:",
|
||||
"Feature flags": "特性标志",
|
||||
"Fetched items: %d/%d.": "已获取项目:%d/%d.",
|
||||
"Fetched items: %d/%d.": "已获取条目:%d/%d.",
|
||||
"Fetching resources: %d/%d": "正在获取资源:%d/%d",
|
||||
"File": "文件",
|
||||
"File system": "文件系统",
|
||||
"Filter tags": "筛选标签",
|
||||
"Find and replace": "查找和替换",
|
||||
"Find: ": "查找:",
|
||||
"Find: ": "查找: ",
|
||||
"Firefox Extension": "Firefox 扩展插件",
|
||||
"Fix search index": "修复搜索索引",
|
||||
"Fixing search index...": "正在修复搜索索引...",
|
||||
@@ -383,6 +397,7 @@
|
||||
"Found: %d.": "已找到:%d 条。",
|
||||
"FTS enabled: %d": "FTS 已开启:%d",
|
||||
"Full changelog": "完整更新记录",
|
||||
"Full name": "完整名称",
|
||||
"General": "常规",
|
||||
"Generated": "已生成",
|
||||
"Generating link...": "生成链接中...",
|
||||
@@ -396,6 +411,7 @@
|
||||
"Headers": "Headers",
|
||||
"Heading": "标题",
|
||||
"Help": "帮助",
|
||||
"Hermes enabled: %d": "已启用Hermes:%d",
|
||||
"Hide %s": "隐藏 %s",
|
||||
"Hide advanced": "隐藏高级的",
|
||||
"Hide disabled": "隐藏禁用的",
|
||||
@@ -420,7 +436,7 @@
|
||||
"Importing notes...": "正在导入笔记...",
|
||||
"Imports data into Joplin.": "导入数据到 Jolin。",
|
||||
"In \"Manual\" mode, attachments are downloaded only when you click on them. In \"Auto\", they are downloaded when you open the note. In \"Always\", all the attachments are downloaded whether you open the note or not.": "“手动” 模式下,仅在单击附件时才会下载。“自动” 模式下,打开笔记,其中的附件就会被全部下载。“总是” 模式下,无论是否打开笔记,所有的附件均会被下载。",
|
||||
"In any command, a note or notebook can be referred to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.": "在任何命令中,某个笔记或笔记本可通过它的名称或 ID 引用,也可使用代表当前所选笔记和笔记本的快捷变量 ‘$n' 和 '$b'。`$c` 可用于引用当前所选的项目。",
|
||||
"In any command, a note or notebook can be referred to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.": "在任何命令中,某个笔记或笔记本可通过它的名称或 ID 引用,也可使用代表当前所选笔记和笔记本的快捷变量 ‘$n' 和 '$b'。`$c` 可用于引用当前所选的条目。",
|
||||
"In order to associate a geo-location with the note, the app needs your permission to access your location.\n\nYou may turn off this option at any time in the Configuration screen.": "为了将地理位置与笔记关联,本应用需要获取您的位置的权限。\n\n您可以在“配置”页面中随时关闭此选项。",
|
||||
"In order to do so, your entire data set will have to be encrypted and synchronised, so it is best to run it overnight.\n\nTo start, please follow these instructions:\n\n1. Synchronise all your devices.\n2. Click \"%s\".\n3. Let it run to completion. While it runs, avoid changing any note on your other devices, to avoid conflicts.\n4. Once sync is done on this device, sync all your other devices and let it run to completion.\n\nImportant: you only need to run this ONCE on one device.": "为此,必须对整个数据集进行加密和同步,因此最好在夜间休息时分运行。\n\n首先,请按照以下说明进行操作:\n\n1. 同步您的所有设备。\n2. 单击 “%s”。\n3. 让其完成运行。在运行时,请不要在其他设备上更改任何笔记,以免发生冲突。\n4. 在此设备上完成同步后,同步其他所有设备,并运行至同步完成。\n\n重要提醒:在一台设备上只需要运行一次。",
|
||||
"In order to use file system synchronisation your permission to write to external storage is required.": "为使用文件系统同步,需要获取写入外部存储的权限。",
|
||||
@@ -450,6 +466,7 @@
|
||||
"Items": "条目",
|
||||
"Items that cannot be decrypted": "无法解密的条目",
|
||||
"Items that cannot be synchronised": "无法同步的条目",
|
||||
"Join us on Twitter": "在Twitter上加入我们",
|
||||
"Joplin can synchronise your notes using various providers. Select one from the list below.": "Joplin 可以使用多种途径来同步您的笔记。可以从下列选项中选择一种方式。",
|
||||
"Joplin Cloud": "Joplin Cloud",
|
||||
"Joplin Cloud email": "Joplin Cloud 邮箱",
|
||||
@@ -478,6 +495,7 @@
|
||||
"Later": "稍后",
|
||||
"Layout": "布局",
|
||||
"Layout button sequence": "布局按钮序列",
|
||||
"Leave it blank to download the language files from the default website": "留空可从默认网站下载语言文件",
|
||||
"Leave notebook...": "离开笔记本...",
|
||||
"Legal": "法律专用纸 (Legal)",
|
||||
"Letter": "信函 (Letter)",
|
||||
@@ -491,6 +509,7 @@
|
||||
"List item": "列表项",
|
||||
"Lists": "列表",
|
||||
"Loaded": "已加载",
|
||||
"Loading...": "正在加载…",
|
||||
"Location": "位置",
|
||||
"Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at \"%s\" and resume the operation.": "锁定文件已被占用。如果您确认当前未在进行任何同步,可在删除锁定文件 “%s” 后继续上一步操作。",
|
||||
"Log": "日志",
|
||||
@@ -518,10 +537,12 @@
|
||||
"Master password:": "主密码(Master password):",
|
||||
"Max concurrent connections": "最大并发连接数",
|
||||
"Max Item Size": "最大条目数",
|
||||
"Max note or attachment size": "最大项目大小",
|
||||
"Max note or attachment size": "最大笔记或附件大小",
|
||||
"Max Total Size": "最大总大小",
|
||||
"Missing keys": "缺少密钥(keys)",
|
||||
"Missing Master Keys": "缺少主密钥(Master Keys)",
|
||||
"Missing required argument: %s": "缺失必选参数:%s",
|
||||
"Missing required flag value: %s": "缺失必选标志值:%s",
|
||||
"Mobile data - auto-sync disabled": "移动数据自动同步被禁用",
|
||||
"More info": "更多信息",
|
||||
"More information": "更多信息",
|
||||
@@ -530,6 +551,7 @@
|
||||
"Move to notebook": "移动到笔记本",
|
||||
"Move to notebook...": "移动到笔记本...",
|
||||
"Move to notebook:": "移动到笔记本:",
|
||||
"Moves the given <item> to [notebook]": "将给定的<item>移动到[notebook]。",
|
||||
"n": "n",
|
||||
"N": "N",
|
||||
"New note": "新建笔记",
|
||||
@@ -561,6 +583,7 @@
|
||||
"Not authentified with %s. Please provide any missing credentials.": "未授予 %s 的权限。请提供缺少的凭据。",
|
||||
"Not downloaded": "未下载",
|
||||
"Not generated": "未生成",
|
||||
"Not now": "不是现在",
|
||||
"note": "笔记",
|
||||
"Note": "笔记",
|
||||
"Note area growth factor": "笔记区域增长因子",
|
||||
@@ -568,6 +591,7 @@
|
||||
"Note attachments...": "笔记附件...",
|
||||
"Note body": "笔记正文",
|
||||
"Note does not exist: \"%s\". Create it?": "笔记不存在:“%s” 。是否创建?",
|
||||
"Note editor": "笔记编辑器",
|
||||
"Note has been saved.": "笔记已被保存。",
|
||||
"Note History": "笔记历史",
|
||||
"Note is not a to-do: \"%s\"": "笔记并非待办事项:“%s”",
|
||||
@@ -591,7 +615,7 @@
|
||||
"OLED Dark": "纯黑 (OLED)",
|
||||
"On %s: %s": "位于 %s: %s",
|
||||
"One of your master keys use an obsolete encryption method.": "您的主密钥(Master Key)之一使用了过时的加密方法。",
|
||||
"One or more items are currently encrypted and you may need to supply a master password. To do so please type `e2ee decrypt`. If you have already supplied the password, the encrypted items are being decrypted in the background and will be available soon.": "一个或多个项目当前已加密,您可能需要提供主密码(master password)。若需进行此操作请输入 `e2ee decrypt` 。若您已提供密码,此时加密文件正在后台解密,解锁之后即可使用。",
|
||||
"One or more items are currently encrypted and you may need to supply a master password. To do so please type `e2ee decrypt`. If you have already supplied the password, the encrypted items are being decrypted in the background and will be available soon.": "一个或多个条目当前已加密,您可能需要提供主密码(master password)。若需进行此操作请输入 `e2ee decrypt` 。若您已提供密码,此时加密文件正在后台解密,解锁之后即可使用。",
|
||||
"One or more master keys need a password.": "一个或多个主密钥(Master Key)需要密码。",
|
||||
"OneDrive": "OneDrive",
|
||||
"OneDrive Login": "登录 OneDrive",
|
||||
@@ -615,6 +639,7 @@
|
||||
"Password:": "密码:",
|
||||
"Passwords do not match!": "密码不匹配!",
|
||||
"Paste": "粘贴",
|
||||
"Paste as text": "粘贴为文本",
|
||||
"Path:": "路径:",
|
||||
"PDF File": "PDF 文件",
|
||||
"Per user. Minimum of %d users.": "每个用户。至少有%d个用户。",
|
||||
@@ -625,6 +650,7 @@
|
||||
"Please enter your password in the master key list below before upgrading the key.": "在升级密钥之前,请在下面的主密钥(Master Key)列表中输入您的密码。",
|
||||
"Please note that if it is a large notebook, it may take a few minutes for all the notes to show up on the recipient's device.": "请注意,如果是大型笔记本,可能需要几分钟时间才能在收件人的设备上显示出所有的笔记。",
|
||||
"Please open the following URL in your browser to authenticate the application. The application will create a directory in \"Apps/Joplin\" and will only read and write files in this directory. It will have no access to any files outside this directory nor to any other personal data. No data will be shared with any third party.": "请在浏览器中打开以下链接以验证本应用程序。本应用会建立 “Apps/Joplin” 文件目录,并只会读写该目录中的文件。本应用没有任何权限访问此目录以外的任何文件或个人信息,也不会与第三方分享任何数据。",
|
||||
"Please record your voice...": "请录下你的声音...",
|
||||
"Please select a notebook first.": "请先选择笔记本。",
|
||||
"Please select the note or notebook to be deleted first.": "请先选择需要删除的笔记或笔记本。",
|
||||
"Please select where the sync status should be exported to": "请选择同步状态的导出位置",
|
||||
@@ -651,6 +677,7 @@
|
||||
"Print": "打印",
|
||||
"Priority support": "优先支持",
|
||||
"Privacy Policy": "隐私政策",
|
||||
"Pro": "Pro",
|
||||
"Process failed payment subscriptions": "处理失败的付费订阅",
|
||||
"Process oversized accounts": "处理超容量的账户",
|
||||
"Process user deletions": "处理用户删除",
|
||||
@@ -693,6 +720,7 @@
|
||||
"Replace all": "全部替换",
|
||||
"Replace with...": "替换为...",
|
||||
"Replace: ": "替换: ",
|
||||
"Reset application layout": "重置应用布局",
|
||||
"Reset master password": "重置主密码(master password)",
|
||||
"Resources: %d.": "资源:%d。",
|
||||
"Restart and upgrade": "重启并升级",
|
||||
@@ -732,6 +760,7 @@
|
||||
"Select all": "全选",
|
||||
"Select emoji...": "选择 emoji...",
|
||||
"Select file...": "选择文件...",
|
||||
"Select parent notebook": "选择父笔记本",
|
||||
"Server is already running on port %d": "服务已在端口 %d 上运行",
|
||||
"Server is not running.": "服务没有运行。",
|
||||
"Server is running on port %d": "服务正在端口 %d 上运行",
|
||||
@@ -747,9 +776,11 @@
|
||||
"Sharing access control": "共享访问控制",
|
||||
"Sharing notebook...": "分享笔记本中...",
|
||||
"Shortcuts are not available in CLI mode.": "快捷键在 CLI 模式下不可用。",
|
||||
"Show advanced": "显示高级选项",
|
||||
"Show Advanced Settings": "显示高级选项",
|
||||
"Show all": "显示全部",
|
||||
"Show completed to-dos": "显示已完成待办事项",
|
||||
"Show disabled": "显示禁用的密钥",
|
||||
"Show disabled keys": "显示禁用的密钥",
|
||||
"Show more actions": "显示更多操作",
|
||||
"Show note counts": "显示笔记数",
|
||||
@@ -763,13 +794,13 @@
|
||||
"Skipped: %d.": "已跳过:%d 条。",
|
||||
"Solarised Dark": "日光暗 (Solarised)",
|
||||
"Solarised Light": "日光亮 (Solarised)",
|
||||
"Some items cannot be decrypted.": "某些项目无法被解密。",
|
||||
"Some items cannot be decrypted.": "某些条目无法被解密。",
|
||||
"Some items cannot be synchronised.": "某些条目无法被同步。",
|
||||
"Some items cannot be synchronised. Press for more info.": "某些条目无法被同步。点按以获取更多信息。",
|
||||
"Sort notebooks by": "笔记本排序方式",
|
||||
"Sort notes by": "笔记排序方式",
|
||||
"Sort selected lines": "排序所选行",
|
||||
"Sorts the item by <field> (eg. title, updated_time, created_time).": "通过 <field> 排序项目(示例:title, updated_time, created_time)。",
|
||||
"Sorts the item by <field> (eg. title, updated_time, created_time).": "通过 <field> 排序条目(示例:title, updated_time, created_time)。",
|
||||
"Source format: %s": "原数据格式:%s",
|
||||
"Source: ": "来源: ",
|
||||
"Specify the port that should be used by the API server. If not set, a default will be used.": "请指定 API 服务器应使用的端口。如果未设置,将使用默认值。",
|
||||
@@ -830,6 +861,7 @@
|
||||
"Tagged: %d.": "已加标签:%d 条。",
|
||||
"Tags": "标签",
|
||||
"Take photo": "拍照",
|
||||
"Task list": "任务列表",
|
||||
"Tasks": "任务",
|
||||
"Teams": "团队",
|
||||
"Text editor command": "文本编辑器命令",
|
||||
@@ -848,12 +880,12 @@
|
||||
"The default encryption method has been changed, you should re-encrypt your data.": "默认的加密方式已变更,您应当重新加密数据。",
|
||||
"The default profile cannot be deleted": "无法删除默认配置文件",
|
||||
"The editor command (may include arguments) that will be used to open a note. If none is provided it will try to auto-detect the default editor.": "该文本编辑器命令(可包含参数)将会被用于打开笔记。若未提供将尝试自动检测默认编辑器。",
|
||||
"The factor property sets how the item will grow or shrink to fit the available space in its container with respect to the other items. Thus an item with a factor of 2 will take twice as much space as an item with a factor of 1.Restart app to see changes.": "拉伸系数属性用于指定项目之间的容量比例。如,因子为 2 的项目所占容量是因子为 1 的项目的两倍。该更改在软件重启后生效。",
|
||||
"The factor property sets how the item will grow or shrink to fit the available space in its container with respect to the other items. Thus an item with a factor of 2 will take twice as much space as an item with a factor of 1.Restart app to see changes.": "拉伸系数属性用于指定条目之间的容量比例。如,因子为 2 的条目所占容量是因子为 1 的条目的两倍。该更改在软件重启后生效。",
|
||||
"The following attachments are being watched for changes:": "下列附件发生的改动正在被监控:",
|
||||
"The following keys use an out-dated encryption algorithm and it is recommended to upgrade them. The upgraded key will still be able to decrypt and encrypt your data as usual.": "以下密钥使用了过时的加密算法,建议对其进行升级。升级后的密钥仍将能够照常解密和加密您的数据。",
|
||||
"The Joplin mobile app does not currently support this type of link: %s": "Joplin 移动应用目前不支持这种类型的链接:%s",
|
||||
"The Joplin team has vetted this plugin and it meets our standards for security and performance.": "Joplin 团队已经核准了该插件,它符合我们对于安全和性能的要求。",
|
||||
"The keys with these IDs are used to encrypt some of your items, however the application does not currently have access to them. It is likely they will eventually be downloaded via synchronisation.": "具有这些 ID 的密钥正被用于加密您的某些项,但应用程序目前无法访问它们。项目最终会通过同步获取,但目前可能仍未被同步。",
|
||||
"The keys with these IDs are used to encrypt some of your items, however the application does not currently have access to them. It is likely they will eventually be downloaded via synchronisation.": "具有这些ID的密钥用于加密某些项目,但应用程序当前无法访问这些密钥。它们很可能最终会通过同步获取。",
|
||||
"The master key has been upgraded successfully!": "主密钥(Master Key)已成功升级!",
|
||||
"The master keys with these IDs are used to encrypt some of your items, however the application does not currently have access to them. It is likely they will eventually be downloaded via synchronisation.": "具有这些 ID 的主密钥(Master Key)正被用于加密某些项,但应用程序目前无法访问它们。项目最终会通过同步获取,但目前可能仍未被同步。",
|
||||
"The note \"%s\" has been successfully restored to the notebook \"%s\".": "笔记 “%s” 已成功恢复到笔记本 “%s” 中。",
|
||||
@@ -868,6 +900,7 @@
|
||||
"The Web Clipper needs your authorisation to access your data.": "网页剪藏器需要您的授权才能访问您的数据。",
|
||||
"The web clipper service is enabled and set to auto-start.": "网页剪藏器已启用并已设置为自动启动。",
|
||||
"The web clipper service is not enabled.": "网页剪藏未启用。",
|
||||
"The WebDAV implementation of %s is incompatible with Joplin, and as such is no longer supported. Please use a different sync method.": "%s的WebDAV工具与Joplin不兼容,因此不再受支持。请使用其他同步方法。",
|
||||
"Theme": "主题",
|
||||
"There are currently no notes. Create one by clicking on the (+) button.": "当前没有任何笔记。点击 (+) 按钮创建。",
|
||||
"There are unsaved changes.": "一些修改尚未保存。",
|
||||
@@ -903,7 +936,7 @@
|
||||
"To manually sort the notes, the sort order must be changed to \"%s\" in the menu \"%s\" > \"%s\"": "欲手动排序笔记,应在菜单 “%2$s” > “%3$s” 中将排序方式调整为 “%1$s”",
|
||||
"To maximise/minimise the console, press \"tc\".": "按 “tc” 最大化/最小化控制台。",
|
||||
"To move from one pane to another, press Tab or Shift+Tab.": "按 Tab 键或 Shift+Tab 组合键切换面板。",
|
||||
"To retry decryption of these items. Run `e2ee decrypt --retry-failed-items`": "运行 `e2ee decrypt —retry-failed-items` 来尝试再次解密这些项目",
|
||||
"To retry decryption of these items. Run `e2ee decrypt --retry-failed-items`": "运行 `e2ee decrypt —retry-failed-items` 来尝试再次解密这些条目",
|
||||
"To switch the profile, the app is going to close and you will need to restart it.": "切换配置文件后,应用程序将会自动关闭,您需要重新启动它。",
|
||||
"To work correctly, the app needs the following permissions. Please enable them in your phone settings, in Apps > Joplin > Permissions": "本应用程序需要下列权限才能正常运作。请在您的手机设置(应用 > Joplin > 权限)中启用它们",
|
||||
"to-do": "待办事项",
|
||||
@@ -920,6 +953,7 @@
|
||||
"Toggle sort order field": "切换排序字段",
|
||||
"Token has been copied to the clipboard!": "令牌已复制到剪贴板!",
|
||||
"Tools": "工具",
|
||||
"Total Size": "总大小",
|
||||
"Total: %d/%d": "总数:%d/%d 条",
|
||||
"Try again": "重试",
|
||||
"Try it now": "现在就试试吧",
|
||||
@@ -931,7 +965,7 @@
|
||||
"Uncompleted to-dos on top": "置顶未完成待办事项",
|
||||
"Undo": "撤销",
|
||||
"Unknown flag: %s": "未知标记:%s",
|
||||
"Unknown item type downloaded - please upgrade Joplin to the latest version": "已下载项目为未知类型,请将 Joplin 升级至最新版本",
|
||||
"Unknown item type downloaded - please upgrade Joplin to the latest version": "已下载条目为未知类型,请将 Joplin 升级至最新版本",
|
||||
"Unordered list": "无序列表",
|
||||
"Unpublish note": "取消分享笔记",
|
||||
"Unshare": "取消分享",
|
||||
@@ -954,11 +988,13 @@
|
||||
"Upgrade the sync target to the latest version.": "升级同步目标到最新版本。",
|
||||
"URL": "URL",
|
||||
"Usage: %s": "使用情况:%s",
|
||||
"Use biometrics to secure access to the app": "使用生物识别技术确保对应用程序的访问安全",
|
||||
"Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE": "使用长列表格式。格式为:ID, NOTE_COUNT(仅笔记本), DATE, TODO_CHECKED(仅待办事项), TITLE",
|
||||
"Use spell checker": "使用拼写检查器",
|
||||
"Use the arrows and page up/down to scroll the lists and text areas (including this console).": "通过方向键与 Page Up / Down 键来滚动列表与文本区域(包含此控制台)。",
|
||||
"Use the arrows to move the layout items. Press \"Escape\" to exit.": "使用箭头移动布局项。按 “Escape” 退出。",
|
||||
"Use this to rebuild the search index if there is a problem with search. It may take a long time depending on the number of notes.": "如果搜索功能遇到问题,可以使用这个重建索引。花费的时间取决于笔记的数量。",
|
||||
"Use your biometrics to secure access to your application. You can always set it up later in Settings.": "使用您的生物特征来确保对应用程序的访问安全。您可以稍后在“设置”中进行设置。",
|
||||
"Used for most text in the markdown editor. If not found, a generic proportional (variable width) font is used.": "用于 markdown 编辑器中的大多数文本。如果没找到,会使用默认(非等宽)字体。",
|
||||
"Used where a fixed width font is needed to lay out text legibly (e.g. tables, checkboxes, code). If not found, a generic monospace (fixed width) font is used.": "用于那些需要使用固定宽度的字体来清晰地布局文本的场景(例如:表格、多选框和代码块)。如果没有找到,会使用默认(等宽)字体。",
|
||||
"User deletions": "用户删除",
|
||||
@@ -970,6 +1006,8 @@
|
||||
"View them now": "立刻查看",
|
||||
"Viewer": "查看器",
|
||||
"Vim": "Vim",
|
||||
"Voice typing language files (URL)": "语音输入语言文件(URL)",
|
||||
"Voice typing...": "语音输入中...",
|
||||
"Warning": "警告",
|
||||
"Warning: not all resources shown for performance reasons (limit: %s).": "警告:由于性能原因无法显示所有资源(最多:%s)。",
|
||||
"Web Clipper": "网页剪藏器",
|
||||
@@ -979,6 +1017,7 @@
|
||||
"WebDAV username": "WebDAV 用户名",
|
||||
"Website and documentation": "网站与文档",
|
||||
"Welcome to Joplin!\n\nType `:help shortcuts` for the list of keyboard shortcuts, or just `:help` for usage information.\n\nFor example, to create a notebook press `mb`; to create a note press `mn`.": "欢迎使用 Joplin!\n\n输入 `:help shortcuts` 获取键盘快捷键列表,或输入 `:help` 获取用法信息。\n\n例:输入 `mb` 新建笔记本;输入 `mn`新建笔记。",
|
||||
"Welcome!": "欢迎!",
|
||||
"When creating a new note:": "当新建笔记时:",
|
||||
"When creating a new to-do:": "当新建待办事项时:",
|
||||
"Words": "单词数",
|
||||
@@ -991,7 +1030,7 @@
|
||||
"You do not have any installed plugin.": "您尚未安装任何插件。",
|
||||
"You may also type `status` for more information.": "输入 `status` 可获取更多信息。",
|
||||
"You may use the tool below to re-encrypt your data, for example if you know that some of your notes are encrypted with an obsolete encryption method.": "您可以使用下面的工具重新加密您的数据。例如当您知道某些笔记使用了过时的加密方法时,可使用该项目。",
|
||||
"Your choice: ": "您的选择:",
|
||||
"Your choice: ": "您的选择: ",
|
||||
"Your data is going to be re-encrypted and synced again.": "您的数据将被重新加密并再次同步。",
|
||||
"Your password is needed to decrypt some of your data.": "要解密您的某些数据,需要使用您的密码。",
|
||||
"Your password is needed to decrypt some of your data. Type `:e2ee decrypt` to set it.": "要解密您的某些数据,需要使用您的密码。输入`:e2ee decrypt`来设置。",
|
||||
|
||||
@@ -1121,7 +1121,25 @@ class Setting extends BaseModel {
|
||||
storage: SettingStorage.File,
|
||||
isGlobal: true,
|
||||
},
|
||||
|
||||
imageResizing: {
|
||||
value: 'alwaysAsk',
|
||||
type: SettingItemType.String,
|
||||
section: 'note',
|
||||
isEnum: true,
|
||||
public: true,
|
||||
appTypes: [AppType.Mobile, AppType.Desktop],
|
||||
label: () => _('Resize large images:'),
|
||||
description: () => _('Shrink large images before adding them to notes to save storage space.'),
|
||||
options: () => {
|
||||
return {
|
||||
alwaysAsk: _('Always ask'),
|
||||
alwaysResize: _('Always resize'),
|
||||
neverResize: _('Never resize'),
|
||||
};
|
||||
},
|
||||
storage: SettingStorage.File,
|
||||
isGlobal: true,
|
||||
},
|
||||
'plugins.states': {
|
||||
value: '',
|
||||
type: SettingItemType.Object,
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "11.0.1",
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/jest": "29.5.3",
|
||||
"@types/js-yaml": "4.0.5",
|
||||
"@types/node": "18.15.13",
|
||||
"@types/node": "18.16.18",
|
||||
"@types/node-rsa": "1.1.1",
|
||||
"@types/react": "17.0.59",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@types/react": "18.0.24",
|
||||
"@types/uuid": "9.0.2",
|
||||
"clean-html": "1.5.0",
|
||||
"jest": "29.5.0",
|
||||
"sharp": "0.32.1",
|
||||
"typescript": "5.0.2"
|
||||
"sharp": "0.32.4",
|
||||
"typescript": "5.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.296.0",
|
||||
@@ -91,7 +91,7 @@
|
||||
"uglifycss": "0.0.29",
|
||||
"url-parse": "1.5.10",
|
||||
"uuid": "9.0.0",
|
||||
"word-wrap": "1.2.3",
|
||||
"word-wrap": "1.2.5",
|
||||
"xml2js": "0.4.23"
|
||||
},
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
|
||||
@@ -70,7 +70,7 @@ export default class EncryptionService {
|
||||
// changed easily since the chunk size is incorporated into the encrypted data.
|
||||
private chunkSize_ = 5000;
|
||||
private decryptedMasterKeys_: Record<string, DecryptedMasterKey> = {};
|
||||
public defaultEncryptionMethod_ = EncryptionMethod.SJCL1b; // public because used in tests
|
||||
public defaultEncryptionMethod_ = EncryptionMethod.SJCL1a; // public because used in tests
|
||||
private defaultMasterKeyEncryptionMethod_ = EncryptionMethod.SJCL4;
|
||||
|
||||
private headerTemplates_ = {
|
||||
|
||||
@@ -5,7 +5,7 @@ import shim from '../../../shim';
|
||||
import PluginService, { defaultPluginSetting, DefaultPluginsInfo, PluginSettings } from '../PluginService';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import * as React from 'react';
|
||||
const shared = require('../../../components/shared/config-shared.js');
|
||||
const shared = require('../../../components/shared/config/config-shared.js');
|
||||
|
||||
const logger = Logger.create('defaultPluginsUtils');
|
||||
|
||||
|
||||
@@ -500,15 +500,23 @@ export default class ShareService {
|
||||
public async maintenance() {
|
||||
if (this.enabled) {
|
||||
let hasError = false;
|
||||
|
||||
try {
|
||||
await this.refreshShareInvitations();
|
||||
await this.refreshShares();
|
||||
Setting.setValue('sync.userId', this.api().userId);
|
||||
} catch (error) {
|
||||
hasError = true;
|
||||
logger.error('Failed to run maintenance:', error);
|
||||
logger.error('Maintenance: Failed to update share invitations:', error);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.refreshShares();
|
||||
} catch (error) {
|
||||
hasError = true;
|
||||
logger.error('Maintenance: Failed to refresh shares:', error);
|
||||
}
|
||||
|
||||
Setting.setValue('sync.userId', this.api().userId);
|
||||
|
||||
// If there was no errors, it means we have all the share objects,
|
||||
// so we can run the clean up function.
|
||||
if (!hasError) await this.updateNoLongerSharedItems();
|
||||
|
||||
@@ -82,10 +82,6 @@ export const parseShareCache = (serialized: string): State => {
|
||||
};
|
||||
};
|
||||
|
||||
export const readFromSettings = (state: RootState): State => {
|
||||
return parseShareCache(state.settings['sync.shareCache']);
|
||||
};
|
||||
|
||||
export function isSharedFolderOwner(state: RootState, folderId: string): boolean {
|
||||
const userId = state.settings['sync.userId'];
|
||||
const share = state[stateRootKey].shares.find(s => s.folder_id === folderId);
|
||||
|
||||
@@ -184,38 +184,42 @@ function shimInit(options = null) {
|
||||
if (shim.isElectron()) {
|
||||
// For Electron
|
||||
const nativeImage = require('electron').nativeImage;
|
||||
let image = nativeImage.createFromPath(filePath);
|
||||
const image = nativeImage.createFromPath(filePath);
|
||||
if (image.isEmpty()) throw new Error(`Image is invalid or does not exist: ${filePath}`);
|
||||
|
||||
const size = image.getSize();
|
||||
|
||||
let mustResize = size.width > maxDim || size.height > maxDim;
|
||||
|
||||
if (mustResize && resizeLargeImages === 'ask') {
|
||||
const answer = shim.showMessageBox(_('You are about to attach a large image (%dx%d pixels). Would you like to resize it down to %d pixels before attaching it?', size.width, size.height, maxDim), {
|
||||
buttons: [_('Yes'), _('No'), _('Cancel')],
|
||||
});
|
||||
|
||||
if (answer === 2) return false;
|
||||
|
||||
mustResize = answer === 0;
|
||||
}
|
||||
|
||||
if (!mustResize) {
|
||||
const saveOriginalImage = async () => {
|
||||
await shim.fsDriver().copy(filePath, targetPath);
|
||||
return true;
|
||||
};
|
||||
const saveResizedImage = async () => {
|
||||
const options = {};
|
||||
if (size.width > size.height) {
|
||||
options.width = maxDim;
|
||||
} else {
|
||||
options.height = maxDim;
|
||||
}
|
||||
const resizedImage = image.resize(options);
|
||||
await shim.writeImageToFile(resizedImage, mime, targetPath);
|
||||
return true;
|
||||
};
|
||||
|
||||
const canResize = size.width > maxDim || size.height > maxDim;
|
||||
if (canResize) {
|
||||
if (resizeLargeImages === 'alwaysAsk') {
|
||||
const Yes = 0, No = 1, Cancel = 2;
|
||||
const userAnswer = shim.showMessageBox(`${_('You are about to attach a large image (%dx%d pixels). Would you like to resize it down to %d pixels before attaching it?', size.width, size.height, maxDim)}\n\n${_('(You may disable this prompt in the options)')}`, {
|
||||
buttons: [_('Yes'), _('No'), _('Cancel')],
|
||||
});
|
||||
if (userAnswer === Yes) return await saveResizedImage();
|
||||
if (userAnswer === No) return await saveOriginalImage();
|
||||
if (userAnswer === Cancel) return false;
|
||||
} else if (resizeLargeImages === 'alwaysResize') {
|
||||
return await saveResizedImage();
|
||||
}
|
||||
}
|
||||
|
||||
const options = {};
|
||||
if (size.width > size.height) {
|
||||
options.width = maxDim;
|
||||
} else {
|
||||
options.height = maxDim;
|
||||
}
|
||||
|
||||
image = image.resize(options);
|
||||
|
||||
await shim.writeImageToFile(image, mime, targetPath);
|
||||
return await saveOriginalImage();
|
||||
} else {
|
||||
// For the CLI tool
|
||||
const image = sharp(filePath);
|
||||
@@ -241,8 +245,6 @@ function shimInit(options = null) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// This is a bit of an ugly method that's used to both create a new resource
|
||||
|
||||
@@ -34,13 +34,13 @@ const { FileApiDriverLocal } = require('../file-api-driver-local');
|
||||
const { FileApiDriverWebDav } = require('../file-api-driver-webdav.js');
|
||||
const { FileApiDriverDropbox } = require('../file-api-driver-dropbox.js');
|
||||
const { FileApiDriverOneDrive } = require('../file-api-driver-onedrive.js');
|
||||
const { FileApiDriverAmazonS3 } = require('../file-api-driver-amazon-s3.js');
|
||||
import SyncTargetRegistry from '../SyncTargetRegistry';
|
||||
const SyncTargetMemory = require('../SyncTargetMemory.js');
|
||||
const SyncTargetFilesystem = require('../SyncTargetFilesystem.js');
|
||||
const SyncTargetNextcloud = require('../SyncTargetNextcloud.js');
|
||||
const SyncTargetDropbox = require('../SyncTargetDropbox.js');
|
||||
const SyncTargetAmazonS3 = require('../SyncTargetAmazonS3.js');
|
||||
const SyncTargetWebDAV = require('../SyncTargetWebDAV.js');
|
||||
import SyncTargetJoplinServer from '../SyncTargetJoplinServer';
|
||||
import EncryptionService from '../services/e2ee/EncryptionService';
|
||||
import DecryptionWorker from '../services/DecryptionWorker';
|
||||
@@ -59,10 +59,10 @@ import Synchronizer from '../Synchronizer';
|
||||
import SyncTargetNone from '../SyncTargetNone';
|
||||
import { setRSA } from '../services/e2ee/ppk';
|
||||
const md5 = require('md5');
|
||||
const { S3Client } = require('@aws-sdk/client-s3');
|
||||
const { Dirnames } = require('../services/synchronizer/utils/types');
|
||||
import RSA from '../services/e2ee/RSA.node';
|
||||
import { State as ShareState } from '../services/share/reducer';
|
||||
import initLib from '../initLib';
|
||||
|
||||
// Each suite has its own separate data and temp directory so that multiple
|
||||
// suites can be run at the same time. suiteName is what is used to
|
||||
@@ -121,6 +121,7 @@ SyncTargetRegistry.addClass(SyncTargetOneDrive);
|
||||
SyncTargetRegistry.addClass(SyncTargetNextcloud);
|
||||
SyncTargetRegistry.addClass(SyncTargetDropbox);
|
||||
SyncTargetRegistry.addClass(SyncTargetAmazonS3);
|
||||
SyncTargetRegistry.addClass(SyncTargetWebDAV);
|
||||
SyncTargetRegistry.addClass(SyncTargetJoplinServer);
|
||||
SyncTargetRegistry.addClass(SyncTargetJoplinCloud);
|
||||
|
||||
@@ -173,6 +174,7 @@ logger.addTarget(TargetType.Console);
|
||||
logger.setLevel(LogLevel.Warn); // Set to DEBUG to display sync process in console
|
||||
|
||||
Logger.initializeGlobalLogger(logger);
|
||||
initLib(logger);
|
||||
|
||||
BaseItem.loadClass('Note', Note);
|
||||
BaseItem.loadClass('Folder', Folder);
|
||||
@@ -623,6 +625,13 @@ async function initFileApi() {
|
||||
const appDir = await api.appDirectory();
|
||||
fileApi = new FileApi(appDir, new FileApiDriverOneDrive(api));
|
||||
} else if (syncTargetId_ === SyncTargetRegistry.nameToId('amazon_s3')) {
|
||||
// (Most of?) the @aws-sdk libraries depend on an old version of uuid
|
||||
// that doesn't work with jest (without converting ES6 exports to CommonJS).
|
||||
//
|
||||
// Require it dynamically so that this doesn't break test environments that
|
||||
// aren't configured to do this conversion.
|
||||
const { FileApiDriverAmazonS3 } = require('../file-api-driver-amazon-s3.js');
|
||||
const { S3Client } = require('@aws-sdk/client-s3');
|
||||
|
||||
// We make sure for S3 tests run in band because tests
|
||||
// share the same directory which will cause locking errors.
|
||||
@@ -916,7 +925,7 @@ class TestApp extends BaseApplication {
|
||||
if (!argv.includes('--profile')) {
|
||||
argv = argv.concat(['--profile', `tests-build/profile/${uuid.create()}`]);
|
||||
}
|
||||
argv = await super.start(['', ''].concat(argv));
|
||||
argv = await super.start(['', ''].concat(argv), { setupGlobalLogger: false });
|
||||
|
||||
// For now, disable sync and encryption to avoid spurious intermittent failures
|
||||
// caused by them interupting processing and causing delays.
|
||||
|
||||
@@ -156,7 +156,7 @@ class Time {
|
||||
}
|
||||
|
||||
public async waitTillCondition(condition: ConditionHandler) {
|
||||
if (condition()) return;
|
||||
if (condition()) return null;
|
||||
|
||||
return new Promise(resolve => {
|
||||
const iid = setInterval(() => {
|
||||
|
||||
@@ -156,7 +156,13 @@ const features = (): Record<FeatureId, PlanFeature> => {
|
||||
teams: true,
|
||||
},
|
||||
collaborate: {
|
||||
title: _('Share and collaborate on a notebook'),
|
||||
title: _('Collaborate on a notebook with others'),
|
||||
basic: true,
|
||||
pro: true,
|
||||
teams: true,
|
||||
},
|
||||
share: {
|
||||
title: _('Share a notebook with others'),
|
||||
basic: false,
|
||||
pro: true,
|
||||
teams: true,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user