diff --git a/.gitignore b/.gitignore index ec9ede186..171e848e7 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ lerna-debug.log .env docs/**/*.mustache .idea +/readme/i18n # Yarn stuff # https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..9716fe9ec --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,23 @@ +project_id: '624298' +api_token_env: CROWDIN_PERSONAL_TOKEN +preserve_hierarchy: true +files: + + - source: /readme/**/* + translation: /readme/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name% + ignore: + - /readme/_i18n + - /readme/i18n + - /readme/about/changelog + - /readme/about/stats.md + - /readme/api + - /readme/dev + - /readme/news + - /readme/cla.md + - /readme/connection_check.md + - /readme/privacy.md + - /**/*.yml + - /**/*.json + - /**/*.png + - /**/*.jpg + \ No newline at end of file diff --git a/joplin.code-workspace b/joplin.code-workspace index a39113b5f..beb8c7eb9 100644 --- a/joplin.code-workspace +++ b/joplin.code-workspace @@ -182,6 +182,11 @@ "docs/images/flags": true, "lerna-debug.log": true, "node_modules/": true, + "packages/doc-builder/build": true, + "packages/doc-builder/help": true, + "packages/doc-builder/news": true, + "packages/doc-builder/i18n": true, + "readme/i18n": true, "packages/app-cli/**/*.*~": true, "packages/app-cli/**/*.mo": true, "packages/app-cli/**/build/": true, diff --git a/package.json b/package.json index 03d162326..66c32e07d 100644 --- a/package.json +++ b/package.json @@ -12,31 +12,34 @@ "node": ">=16" }, "scripts": { - "buildParallel": "yarn workspaces foreach --verbose --interlaced --parallel --jobs 2 --topological run build && yarn run tsc", - "buildSequential": "yarn workspaces foreach --verbose --interlaced --topological run build && yarn run tsc", "buildApiDoc": "yarn workspace joplin start apidoc ../../readme/api/references/rest_api.md", "buildCommandIndex": "node packages/tools/gulp/tasks/buildCommandIndexRun.js", + "buildParallel": "yarn workspaces foreach --verbose --interlaced --parallel --jobs 2 --topological run build && yarn run tsc", "buildPluginDoc": "cd packages/generate-plugin-doc && yarn run buildPluginDoc_", - "updateMarkdownDoc": "node ./packages/tools/updateMarkdownDoc", - "updateNews": "node ./packages/tools/website/updateNews", - "postPreReleasesToForum": "node ./packages/tools/postPreReleasesToForum", + "buildSequential": "yarn workspaces foreach --verbose --interlaced --topological run build && yarn run tsc", + "buildServerDocker": "node packages/tools/buildServerDocker.js", "buildSettingJsonSchema": "yarn workspace joplin start settingschema ../../../joplin-website/docs/schema/settings.json", "buildTranslations": "node packages/tools/build-translation.js", - "buildWebsiteTranslations": "node packages/tools/website/buildTranslations.js", "buildWebsite": "node ./packages/tools/website/processDocs.js --env prod && node ./packages/tools/website/build.js && yarn run buildPluginDoc && yarn run buildSettingJsonSchema", - "checkLibPaths": "node ./packages/tools/checkLibPaths.js", + "buildWebsiteTranslations": "node packages/tools/website/buildTranslations.js", "checkIgnoredFiles": "node ./packages/tools/checkIgnoredFiles.js", + "checkLibPaths": "node ./packages/tools/checkLibPaths.js", "circularDependencyCheck": "madge --warning --circular --extensions js ./", "clean": "npm run clean --workspaces --if-present && node packages/tools/clean && yarn cache clean", + "crowdin": "crowdin", + "crowdinDownload": "crowdin download", + "crowdinUpload": "crowdin upload", + "cspell": "cspell", "dependencyTree": "madge", "generateDatabaseTypes": "node packages/tools/generate-database-types", "linkChecker": "linkchecker https://joplinapp.org", "linter-ci": "eslint --resolve-plugins-relative-to . --quiet --ext .js --ext .jsx --ext .ts --ext .tsx", + "linter-interactive": "eslint-interactive --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx", "linter-precommit": "eslint --resolve-plugins-relative-to . --fix --ext .js --ext .jsx --ext .ts --ext .tsx", "linter": "eslint --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx", - "linter-interactive": "eslint-interactive --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx", "packageJsonLint": "node ./packages/tools/packageJsonLint.js", "postinstall": "gulp build", + "postPreReleasesToForum": "node ./packages/tools/postPreReleasesToForum", "publishAll": "git pull && yarn run buildParallel && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll", "releaseAndroid": "PATH=\"/usr/local/opt/openjdk@11/bin:$PATH\" node packages/tools/release-android.js", "releaseAndroidClean": "node packages/tools/release-android.js", @@ -47,15 +50,15 @@ "releasePluginGenerator": "node packages/tools/release-plugin-generator.js", "releasePluginRepoCli": "node packages/tools/release-plugin-repo-cli.js", "releaseServer": "node packages/tools/release-server.js", - "cspell": "cspell", + "setupNewRelease": "node ./packages/tools/setupNewRelease", "spellcheck": "node packages/tools/spellcheck.js", "tagServerLatest": "node packages/tools/tagServerLatest.js", - "buildServerDocker": "node packages/tools/buildServerDocker.js", - "setupNewRelease": "node ./packages/tools/setupNewRelease", "test-ci": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 2 run test-ci", "test": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 2 run test", "tsc": "yarn workspaces foreach --parallel --verbose --interlaced run tsc", "updateIgnored": "node packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js", + "updateMarkdownDoc": "node ./packages/tools/updateMarkdownDoc", + "updateNews": "node ./packages/tools/website/updateNews", "updatePluginTypes": "./packages/generator-joplin/updateTypes.sh", "watch": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 999 run watch", "watchWebsite": "nodemon --delay 1 --watch Assets/WebsiteAssets --watch packages/tools/website --watch packages/tools/website/utils --watch packages/doc-builder/build --ext md,ts,js,mustache,css,tsx,gif,png,svg --exec \"node packages/tools/website/build.js && http-server --port 8077 ../joplin-website/docs -a localhost\"" @@ -66,6 +69,7 @@ } }, "devDependencies": { + "@crowdin/cli": "3", "@joplin/utils": "~2.12", "@seiyab/eslint-plugin-react-hooks": "4.5.1-beta.0", "@typescript-eslint/eslint-plugin": "6.0.0", diff --git a/packages/doc-builder/.gitignore b/packages/doc-builder/.gitignore index 95ae54d16..3fc22572a 100644 --- a/packages/doc-builder/.gitignore +++ b/packages/doc-builder/.gitignore @@ -8,11 +8,12 @@ .docusaurus .cache-loader -# Docs are auto-generated using processDoc.js +# Folders that are auto-generated using processDocs.js /docs /help /blog /news +/i18n # Misc .DS_Store diff --git a/packages/doc-builder/docusaurus.config.js b/packages/doc-builder/docusaurus.config.js index c82cfa535..131080cdc 100644 --- a/packages/doc-builder/docusaurus.config.js +++ b/packages/doc-builder/docusaurus.config.js @@ -27,7 +27,7 @@ const config = { // to replace "en" with "zh-Hans". i18n: { defaultLocale: 'en', - locales: ['en'], + locales: ['en', 'fr'], }, plugins: [ @@ -116,6 +116,10 @@ const config = { className: 'navbar-custom-buttons sponsor-button', target: '_self', }, + { + type: 'localeDropdown', + position: 'right', + }, ], }, footer: { diff --git a/packages/tools/release-website.sh b/packages/tools/release-website.sh index dc45e192f..cc05d7f6d 100755 --- a/packages/tools/release-website.sh +++ b/packages/tools/release-website.sh @@ -40,11 +40,11 @@ yarn install # to change after installation. git reset --hard -JOPLIN_GITHUB_OAUTH_TOKEN=$JOPLIN_GITHUB_OAUTH_TOKEN yarn run updateMarkdownDoc +JOPLIN_GITHUB_OAUTH_TOKEN=$JOPLIN_GITHUB_OAUTH_TOKEN yarn updateMarkdownDoc # Automatically update certain forum posts -yarn run updateNews $DISCOURSE_API_KEY $DISCOURSE_USERNAME -yarn run postPreReleasesToForum $DISCOURSE_API_KEY $DISCOURSE_USERNAME +yarn updateNews $DISCOURSE_API_KEY $DISCOURSE_USERNAME +yarn postPreReleasesToForum $DISCOURSE_API_KEY $DISCOURSE_USERNAME # We commit and push the change. It will be a noop if nothing was actually # changed @@ -67,7 +67,8 @@ git checkout master git pull --rebase cd "$JOPLIN_ROOT_DIR" -yarn run buildWebsite +yarn crowdinDownload +yarn buildWebsite cd "$JOPLIN_WEBSITE_ROOT_DIR" git add -A diff --git a/packages/tools/website/processDocs.test.ts b/packages/tools/website/processDocs.test.ts index d5c99db95..8959c21e1 100644 --- a/packages/tools/website/processDocs.test.ts +++ b/packages/tools/website/processDocs.test.ts @@ -1,5 +1,5 @@ import { readFile } from 'fs/promises'; -import { processMarkdownDoc } from './processDocs'; +import { processMarkdownDoc, processUrls } from './processDocs'; import { basename } from 'path'; import { readdirSync } from 'fs'; @@ -47,4 +47,34 @@ ${actual}`); expect(actual).toBe(expected); }); + test.each([ + [ + '', + '', + ], + [ + '[synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/joplin_cloud.md)', + '[synchronisation set to Joplin Cloud](/help/apps/sync/joplin_cloud)', + ], + [ + 'The notes can be securely [synchronised](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/index.md) using [end-to-end encryption](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/e2ee.md)', + 'The notes can be securely [synchronised](/help/apps/sync) using [end-to-end encryption](/help/apps/sync/e2ee)', + ], + [ + 'The notes can be securely [synchronised](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/index.md) using [end-to-end encryption](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/e2ee.md)', + 'The notes can be securely [synchronised](/help/apps/sync) using [end-to-end encryption](/help/apps/sync/e2ee)', + ], + [ + '[Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md)', + '[Configuration screen](/help/apps/config_screen) [Configuration screen](/help/apps/config_screen)', + ], + [ + 'In [command-line mode](https://github.com/laurent22/joplin/blob/dev/readme/apps/terminal.md#command-line-mode), type `import --format md /path/to/file.md`', + 'In [command-line mode](/help/apps/terminal#command-line-mode), type `import --format md /path/to/file.md`', + ], + ])('should process URLs', (input, expected) => { + const actual = processUrls(input); + expect(actual).toBe(expected); + }); + }); diff --git a/packages/tools/website/processDocs.ts b/packages/tools/website/processDocs.ts index 7bcf886ac..e21548d23 100644 --- a/packages/tools/website/processDocs.ts +++ b/packages/tools/website/processDocs.ts @@ -313,10 +313,10 @@ const resolveBlockQuotes = (output: string): string => { return newOutput.join('\n'); }; -const processUrls = (md: string) => { +export const processUrls = (md: string) => { md = md - .replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*)\/index\.md/g, '/help/$1') - .replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*)\.md/g, '/help/$1'); + .replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*?)\/index\.md/g, '/help/$1') + .replace(/https:\/\/github.com\/laurent22\/joplin\/blob\/dev\/readme\/(.*?)\.md/g, '/help/$1'); return md; }; @@ -479,6 +479,7 @@ async function main() { await processDocFiles(readmeDir, destHelpDir, [ `${readmeDir}/_i18n`, + `${readmeDir}/i18n`, `${readmeDir}/cla.md`, `${readmeDir}/download.md`, `${readmeDir}/faq_joplin_cloud.md`, @@ -495,6 +496,14 @@ async function main() { await processDocFiles(`${readmeDir}/news`, newsDestDir, [], newsContext); await deleteUnprocessedFiles(newsDestDir, newsContext.processedFiles); + if (await pathExists(`${readmeDir}/i18n`)) { + const localeContext: Context = { donateLinks }; + await processDocFiles(`${readmeDir}/i18n`, `${docBuilderDir}/i18n`, [], localeContext); + await deleteUnprocessedFiles(`${docBuilderDir}/i18n`, localeContext.processedFiles); + } else { + console.info('i18n folder is missing - skipping it'); + } + await copyFile(`${rootDir}/Assets/WebsiteAssets/images`, `${docBuilderDir}/static/images`); if (config.docusaurusBuildEnabled) { diff --git a/readme/apps/email_to_note.md b/readme/apps/email_to_note.md index 52c7597ac..92fb3426a 100644 --- a/readme/apps/email_to_note.md +++ b/readme/apps/email_to_note.md @@ -10,13 +10,13 @@ This feature is available for Pro and Teams members. ### Desktop -To copy your Joplin Cloud email address you will need to navigate to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and locate to the Joplin Cloud tab. You will need to have your [synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/welcome/3_synchronising_your_notes.md#setting-up-joplin-cloud-synchronisation) +To copy your Joplin Cloud email address you will need to navigate to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and locate to the Joplin Cloud tab. You will need to have your [synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/joplin_cloud.md) ### Mobile -To copy your Joplin Cloud email address you will need to navigate to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and find the Joplin Cloud section. You will need to have your [synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/welcome/3_synchronising_your_notes.md#setting-up-joplin-cloud-synchronisation) +To copy your Joplin Cloud email address you will need to navigate to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md) and find the Joplin Cloud section. You will need to have your [synchronisation set to Joplin Cloud](https://github.com/laurent22/joplin/blob/dev/readme/apps/sync/joplin_cloud.md) diff --git a/readme/apps/import_export.md b/readme/apps/import_export.md index 3e50ee90a..e90963f18 100644 --- a/readme/apps/import_export.md +++ b/readme/apps/import_export.md @@ -21,10 +21,13 @@ In the **terminal application**, in [command-line mode](https://github.com/laure Joplin can import notes from plain Markdown file. You can either import a complete directory of Markdown files or individual files. In the **desktop application**: + * **File import**: Go to File > Import > MD - Markdown (file) and select the Markdown file. This file will then be imported to the currently selected Notebook. * **Directory import**: Go to File > Import > MD - Markdown (directory) and select the top level of the directory that is being imported. Directory (folder) structure will be preserved in the Notebook > Subnotebook > Note structure within Joplin. -In the **terminal application**, in [command-line mode](https://github.com/laurent22/joplin/blob/dev/readme/apps/terminal.md#command-line-mode), type `import --format md /path/to/file.md` or `import --format md /path/to/directory/`. +In the **terminal application**, in [command-line mode](https://github.com/laurent22/joplin/blob/dev/readme/apps/terminal.md#command-line-mode): + +Type `import --format md /path/to/file.md` or `import --format md /path/to/directory/`. ### Importing from other applications diff --git a/readme/apps/sync/joplin_cloud.md b/readme/apps/sync/joplin_cloud.md new file mode 100644 index 000000000..5997aeb64 --- /dev/null +++ b/readme/apps/sync/joplin_cloud.md @@ -0,0 +1,5 @@ +# Joplin Cloud synchronisation + +[Joplin Cloud](https://joplinapp.org/plans/) is a web service specifically designed for Joplin. Besides synchronising your data, it also allows you to publish a note to the internet, or share a notebook with your friends, family or colleagues. Joplin Cloud, compared to other services, also features a number of performance improvements allowing for faster synchronisation. + +To use it, go to the [Configuration screen](https://github.com/laurent22/joplin/blob/dev/readme/apps/config_screen.md), then to the Synchronisation section. In the list of sync targets, select "Joplin Cloud". Enter your email and password, and you're ready to use Joplin Cloud. diff --git a/readme/welcome/3_synchronising_your_notes.md b/readme/welcome/3_synchronising_your_notes.md index fa299dabb..f4f90a037 100644 --- a/readme/welcome/3_synchronising_your_notes.md +++ b/readme/welcome/3_synchronising_your_notes.md @@ -6,7 +6,7 @@ Joplin allows you to synchronise your data using various file hosting services. [Joplin Cloud](https://joplinapp.org/plans/) is a web service specifically designed for Joplin. Besides synchronising your data, it also allows you to publish a note to the internet, or share a notebook with your friends, family or colleagues. Joplin Cloud, compared to other services, also features a number of performance improvements allowing for faster synchronisation. -To use it, go to the config screen, then to the Synchronisation section. In the list of sync target, select "Joplin Cloud". Enter your email and password, and you're ready to use Joplin Cloud. +To use it, go to the config screen, then to the Synchronisation section. In the list of sync targets, select "Joplin Cloud". Enter your email and password, and you're ready to use Joplin Cloud. ## Setting up Dropbox synchronisation diff --git a/yarn.lock b/yarn.lock index 34b07d00f..36fe0597a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4225,6 +4225,21 @@ __metadata: languageName: node linkType: hard +"@crowdin/cli@npm:3": + version: 3.15.0 + resolution: "@crowdin/cli@npm:3.15.0" + dependencies: + command-exists-promise: ^2.0.2 + node-fetch: 2.6.7 + shelljs: ^0.8.4 + tar: ^4.4.8 + yauzl: ^2.10.0 + bin: + crowdin: jdeploy-bundle/jdeploy.js + checksum: 232f455d9ba44357d8f107ed7471b642e20ae724ebe8ce28175219223225f1c6ca77d7c69b220fe45db7ce1f06774d5d9a5a46100e5aa948a89743ea0eb6b7c1 + languageName: node + linkType: hard + "@cspell/cspell-bundled-dicts@npm:^5.21.2": version: 5.21.2 resolution: "@cspell/cspell-bundled-dicts@npm:5.21.2" @@ -15501,6 +15516,13 @@ __metadata: languageName: node linkType: hard +"command-exists-promise@npm:^2.0.2": + version: 2.0.2 + resolution: "command-exists-promise@npm:2.0.2" + checksum: f6674abbc7d9cc704255999adb42e8b8fe165d941de207d1df8177e1ccea2afb9ff57aad7a70f9235056dd317e45b31f9726ecb2c39826f9a1f98a50f4de1b31 + languageName: node + linkType: hard + "command-exists@npm:^1.2.8": version: 1.2.9 resolution: "command-exists@npm:1.2.9" @@ -36493,6 +36515,7 @@ __metadata: version: 0.0.0-use.local resolution: "root@workspace:." dependencies: + "@crowdin/cli": 3 "@joplin/utils": ~2.12 "@seiyab/eslint-plugin-react-hooks": 4.5.1-beta.0 "@types/fs-extra": 11.0.2